Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
conduct behavioral
research online
structure content
Display instructions to the What the instructions say
participant
How long the image should
Show an image and be displayed
measure response time for
a keyboard response What keys the participant
is allowed to press
Display a question with a
likert scale and record the How many response
response options are on the scale
STRUCTURE & CONTENT
jsPsych.turk jsPsych.pluginAPI
Functions for interacting with Helpful functions for developing
Mechanical Turk. plugins. Includes methods for
getting keyboard responses and
processing plugin parameters.
WHAT'S A PLUGIN?
{
… define a single, atomic unit of the experiment.
jspsych-single-stim.js
Display a stimulus on the screen and record what key the
participant presses in response and the response time.
Parameters control: what stimulus is presented, what keys can be pressed, how
long stimulus is displayed, how long participant has to respond
PLUGIN EXAMPLES
jspsych-instructions.js
Display a set of instructions to the participant
Parameters control: what the instructions say, whether the participant can go back
to previous pages to re-read, whether keys or the mouse are used to navigate
PLUGIN EXAMPLES
jspsych-visual-search-circle.js
Perform a trial in a visual search task with search array
organized in a circle around a fixation point.
Parameters control: search array size, display size, target/distractor image, fixation
image, response keys, maximum search duration, fixation duration
PLUGIN EXAMPLES
EXPERIMENT END
Every experiment has a timeline
EXPERIMENT START THE TIMELINE
EXPERIMENT END
Timelines are ordered lists of trials
EXPERIMENT START THE TIMELINE
EXPERIMENT END
Timelines can be linear
EXPERIMENT START THE TIMELINE
EXPERIMENT END
REPEAT UNTIL...
EXPERIMENT END
IF...
… or conditionals
TO CREATE AN
EXPERIMENT, SPECIFY
THE TIMELINE
FEATURES OF JSPSYCH
3 concerns hardware
Variations in computer hardware can cause SUGGESTED READING
measurement differences of 10-100ms. Online
experiments will have variability in hardware. Brand & Bradley (2012). doi:10.1177
/0894439311415604
JavaScript response times* are a bit slower (10-40ms) de Leeuw & Motz (2015). doi:10.3758
than MATLAB Psychtoolbox, but have equivalent /s13428-015-0567-2
variance. Plant & Turner (2009). doi:10.3758/BRM.
* using the most conservative measurement strategy 41.3.598
Display duration is longer than requested, by about 20ms on average. The exact
length depends on the machine and browser.
var x = 123;
x = 'hello'; // no error
VARIABLES IN JAVASCRIPT
function alertmsg(x){
message = x();
alert(message);
}
This line will show the
alertmsg(f);
message hello world.
VARIABLES IN JAVASCRIPT
};
{
a programming-friendly text editor
https://atom.io
docs.jspsych.org/tutorials/hello-world
<!doctype html>
<html>
<head>
<title>Hello world experiment</title>
</head>
<body>
</body>
</html>
HELLO, WORLD!
<!doctype html>
<html>
<head>
<title>Hello world experiment</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src="jspsych-4.3/jspsych.js"></script>
</head>
<body>
</body>
</html>
HELLO, WORLD!
<!doctype html>
<html>
<head>
<title>Hello world experiment</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src="jspsych-4.3/jspsych.js"></script>
<link href="jspsych-4.3/css/jspsych.css" rel="stylesheet"></link>
</head>
<body>
</body>
</html>
HELLO, WORLD!
<!doctype html>
<html>
<head>
<title>Hello world experiment</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src="jspsych-4.3/jspsych.js"></script>
<script src="jspsych-4.3/plugins/jspsych-text.js"></script>
<link href="jspsych-4.3/css/jspsych.css" rel="stylesheet"></link>
</head>
<body>
</body>
</html>
HELLO, WORLD!
<!doctype html>
<html>
<head>
...
</head>
<body>
</body>
<script>
var hello_trial = {
type: 'text',
text: 'hello, world!'
}
jsPsych.init({
experiment_structure: [hello_trial]
});
</script>
</html>
LEXICAL DECISION TASK
/* experiment parameters */
var low_frequency_words = ['cove','turf','twig','foyer','denim'];
var high_frequency_words = ['chair','city','girl','food','dark'];
var nonwords = ['cowe','turv','twif','foger','dewim','thair','ciny','birl','rood','zark'];
</script>
</html>
LEXICAL DECISION TASK
adding the instructions
...
<script>
/* experiment parameters */
...
/* instructions */
var instructions = {
type: 'instructions',
pages: ['<p>You are going to see a series of individual words, some of which are ' +
'actual English words, while others are nonsense words that look like '+
'English words. Your job is to indicate whether the word is a real English '+
'word as quickly and accurately as you can.</p>'+
'<p style="font-weight:bold;">Press Y if the word is an English word.</p>'+
'<p style="font-weight:bold;">Press N if the word is not an English word.</p>'+
'<p>Click the button below to begin.</p>'],
allow_keys: false,
show_clickable_nav: true
}
timeline.push(instructions);
</script>
...
LEXICAL DECISION TASK
initialize the experiment
...
<script>
/* experiment parameters */
...
/* instructions */
...
</script>
...
LEXICAL DECISION TASK
adding the test trials
...
/* experiment parameters */
...
/* instructions */
...
/* instructions */
...
/* instructions */
...
/* instructions */
...
timeline = timeline.concat(all_trials);
/* instructions */
...
timeline = timeline.concat(all_trials);
psiturk - Use psiturk to launch a server on your computer and store data
https://github.com/jodeleeuw/sample-jspsych-psiturk-experiment
jatos - Just Another Tool for Online Studies has example jspsych experiments.
https://github.com/JATOS/JATOS/wiki/Example-Studies
keen.io - A third-party service that lets you write data to their servers, without
having a server-side script to write data.
PLUGIN
DEVELOPMENT
CREATING A NEW PLUGIN
Sometimes you can use existing plugins to build an experiment, but it would
be easier to implement a plugin. For example, a visual search task could be
done with the single-stim plugin, but a custom visual search plugin made it
easier to create the experiment (and share the plugin).
CREATING A NEW PLUGIN
an empty plugin
jsPsych['plugin-name'] = (function(){
plugin.create = function(params){
var trials = [];
trials.push({});
return trials;
}
return plugin;
})();
CREATING A NEW PLUGIN
an empty plugin
jsPsych is an object. This adds a new property to jsPsych['plugin-name'] = (function(){
the jsPsych object with the name 'plugin-name'
var plugin = {};
plugin.create = function(params){
var trials = [];
trials.push({});
return trials;
}
return plugin;
})();
CREATING A NEW PLUGIN
an empty plugin
This strange looking syntax is actually a neat jsPsych['plugin-name'] = (function(){
feature of JavaScript that enables persistence
and state. Functionally, it ensures that plugins var plugin = {};
are encapsulated and protected from plugin.create = function(params){
interference from other code. var trials = [];
trials.push({});
return trials;
}
return plugin;
})();
CREATING A NEW PLUGIN
an empty plugin
jsPsych['plugin-name'] = (function(){
plugin.create = function(params){
var trials = [];
trials.push({});
return trials;
}
return plugin;
})();
CREATING A NEW PLUGIN
an empty plugin
jsPsych['plugin-name'] = (function(){
return plugin;
})();
CREATING A NEW PLUGIN
an empty plugin
jsPsych['plugin-name'] = (function(){
plugin.create = function(params){
var trials = [];
trials.push({});
return plugin;
This method must call jsPsych.finishTrial() when it
is done running the trial. })();
CREATING A NEW PLUGIN
an empty plugin
jsPsych['plugin-name'] = (function(){
plugin.create = function(params){
var trials = [];
trials.push({});
return trials;
}
jsPsych['random-number'] = (function(){
plugin.create = function(params){
var trials = [];
name the plugin
return trials;
}
The convention is to name the file containing the
plugin jspsych-plugin-name.js. This plugin is plugin.trial = function(display_element, trial){
going to generate a random number and display it, jsPsych.finishTrial();
so we will call it random-number. The plugin file }
would be jspsych-random-number.js.
return plugin;
})();
CREATING A NEW PLUGIN
jsPsych['random-number'] = (function(){
plugin.create = function(params){
var trials = [];
add plugin parameters
trials.push({
number: Math.random() * params.multiplier
You can define any parameters that you want in });
the create method. You can perform computations
on the parameters passed in from the timeline if return trials;
necessary. }
return plugin;
})();
CREATING A NEW PLUGIN
jsPsych['random-number'] = (function(){
plugin.create = function(params){
...
}
display content plugin.trial = function(display_element, trial){
display_element.html(
You will probably want to show something on the '<p>The number is: ' + trial.number + '</p>'
screen. There are lots of ways to do this, including );
the append and html methods. jsPsych.finishTrial();
}
return plugin;
})();
CREATING A NEW PLUGIN
jsPsych['random-number'] = (function(){
plugin.create = function(params){
...
}
allow content to persist plugin.trial = function(display_element, trial){
display_element.html(
In order for the display to be visible for a '<p>The number is: ' + trial.number + '</p>'
perceivable amount of time, we need to delay the );
execution of the end of the trial. setTimeout is the setTimeout(function(){
go-to option in JavaScript for delayed execution. display_element.empty();
jsPsych.finishTrial();
}, 1000);
}
return plugin;
})();
CREATING A NEW PLUGIN
jsPsych['random-number'] = (function(){
plugin.create = function(params){
...
}
saving data plugin.trial = function(display_element, trial){
display_element.html(
All plugins should write data after each trial. The '<p>The number is: ' + trial.number + '</p>'
jsPsych.data.write() method will save data );
and automatically add a set of default data as well. setTimeout(function(){
display_element.empty();
jsPsych.data.write({
number: trial.number
});
jsPsych.finishTrial();
}, 1000);
}
return plugin;
})();
CREATING A NEW PLUGIN
var random_number_trial = {
using the plugin type: 'random-number',
multiplier: 15
The type argument in a trial { } will match the name }
given to the plugin. We used a single parameter jsPsych.init({
called multiplier, which we've set to be 15. experiment_structure: [random_number_trial],
on_finish: function(){jsPsych.data.displayData();}
});
ADVANCED
DESIGN
PATTERNS
ADVANCED DESIGN
PATTERNS
var fixation_trial = {
type: 'single-stim',
stimuli: ['<p style='text-align:center'>+</p>'],
pattern 1: sub-trials is_html: true,
timing_response: 500,
timing_post_trial: 0,
You want to create a trial for which there is no choices: 'none'
}
plugin, but the trial could be accomplished by
combining multiple plugins in sequence. for(var i=0; i<words.length; i++){
timeline.push(fixation_trial);
You could create a new plugin, or you could use
the existing plugins to construct a new trial. timeline.push({
type: 'single-stim',
stimuli: [
A simple example: show a fixation cross before '<p style='text-align:center'>'+words[i]+'</p>'
each word in the lexical decision task. ],
timing_response: 2000,
choices: ['y','n'],
is_html: true,
});
}
ADVANCED DESIGN
PATTERNS
var response_trial = {
type: 'single-stim',
stimuli: ['Press P!'],
is_html: true,
on_finish: function(data){
pattern 2: event handlers var is_correct = (data.key_press == 80);
jsPsych.data.addDataToLastTrial({
You want to perform some action that is correct: is_correct
contingent upon what the participant did in the });
}
last trial. }
var show_score = {
type: 'text',
text: function(){
var alldata = jsPsych.data.getData();
var correct_responses = 0;
pattern 3: use functions as params var total_responses = 0;
for(i in alldata){
You want to set a parameter value in a trial that if(alldata[i].test == true){
depends on how the participant has responded total_responses++;
if(alldata[i].correct == true){
so far in the experiment. correct_responses++;
}
For example, you want to show the participant }
their correct response rate so far. }
var p = correct_responses / total_responses;
var percent = Math.round(p*100);
return "You have answered "+percent+"%"+
" of the questions correctly so far.";
}
};
ADVANCED DESIGN
PATTERNS
var training_trials = {
type: 'categorize',
// … other parameters here … //
}
var test_trial = {
type: 'single-stim',
// … other parameters here … //
}
var feedback_chunk = {
For example, you want to display feedback on a chunk_type: 'if',
trial that doesn't have feedback support built-in timeline: [feedback_trial],
to the plugin. conditional_function: function(){
var data = jsPsych.data.getLastTrialData();
if(data.key_press == 89){
return true;
} else {
return false;
}
}
}