Giter VIP home page Giter VIP logo

jspsych's Introduction

jspsych logo

jsPsych is a JavaScript framework for creating behavioral experiments that run in a web browser.

Experiments in jsPsych are created using plugins. Each plugin defines different kinds of events, like showing an image on the screen, and collects different kinds of data, like recording which key was pressed at which time. By assembling different plugins together into a timeline, it is possible to create a wide range of online experiments.

What can I do with jsPsych?

jsPsych comes with a number of plugins that you can use create tasks and collect data. Some plugins do general things, like present a stimulus (text, image, audio, video) and record a key press or button response along with a response time. Other plugins do more specific things, like show a set of instructions pages, run a drag-and-drop image sorting task, or calibrate the WebGazer eye-tracking extension. See the list of all plugins to see what each plugin can do.

Often people can create their experiment by combining these plugins together. But if that's not possible for your experiment, you can also modify a plugin file or create your own plugin. This gives you the flexibility to do exactly what you want, while still taking advantage of jsPsych's general experiment-building framework. The plugin template is extremely flexible. If a task is possible to do in a web browser, you can almost certainly implement it as a plugin.

Getting started

jsPsych can be loaded into a project in a variety of ways, including via CDNs and through NPM. You can learn more about setting up a project by following the hello world tutorial on the jsPsych website.

Once you've got a project set up, the reaction time task tutorial is a great next step, since it covers many core topics and features.

There are also a number of video tutorials available on the website.

Examples

Several example experiments and plugin demonstrations are available in the /examples folder. After you've downloaded the latest release, double-click on an example HTML file to run it in your web browser, and open it with a programming-friendly text editor to see how it works.

Documentation

Documentation is available at https://www.jspsych.org.

Getting help

For questions about using the library, please use the GitHub discussions forum. You can also browse through the history of Q&A on the forum to find related questions.

Contributing

We ❤️ contributions! See the contributing to jsPsych documentation page for more information about how you can help.

Citation

If you use this library in academic work, the preferred citation is:

de Leeuw, J.R., Gilbert, R.A., & Luchterhandt, B. (2023). jsPsych: Enabling an open-source collaborative ecosystem of behavioral experiments. Journal of Open Source Software, 8(85), 5351, https://joss.theoj.org/papers/10.21105/joss.05351.

This paper is an updated description of jsPsych and includes all current core team members. It replaces the earlier paper that described jsPsych:

de Leeuw, J.R. (2015). jsPsych: A JavaScript library for creating behavioral experiments in a Web browser. Behavior Research Methods, 47(1), 1-12. doi:10.3758/s13428-014-0458-y

Citations help us demonstrate that this library is used and valued, which allows us to continue working on it.

Contributors

jsPsych is open source project with numerous contributors. The project is currently managed by the core team of Josh de Leeuw (@jodeleeuw), Becky Gilbert (@becky-gilbert), and Björn Luchterhandt (@bjoluc).

jsPsych was created by Josh de Leeuw.

We're also grateful for the generous support from a Mozilla Open Source Support award, which funded development of the library from 2020-2022.

jspsych's People

Contributors

alisdt avatar andytwoods avatar awhug avatar becky-gilbert avatar bjoluc avatar chrisbrickhouse avatar cjungerius avatar dependabot[bot] avatar dillonplunkett avatar gavinq1 avatar gej1 avatar github-actions[bot] avatar jadeddelta avatar janakl4us avatar jodeleeuw avatar jsato8094 avatar kristiyip avatar kurokida avatar lbai001 avatar mariansauter avatar nikbpetrov avatar pablobernabeu avatar pjkohler avatar rivasd avatar robawilkinson avatar shamrt avatar sprengholz avatar vijaymarupudi avatar vrsivananda avatar wolfgangwalther avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

jspsych's Issues

remove utils folder

functions can be merged into either the related plugins or the core library.

Wiki examples should have downloadable zip files

Should allow people to download each example with a self-contained folder, so that opening the .html file in their browser locally will work. This lets people tinker with the page more directly with fewer steps to get through.

Add utility methods for Turk

Add utility methods for grabbing minimal information from Turk:

  • If HIT has been accepted, or if in preview on the turk website.
  • Worker ID
  • HIT ID
  • Assignment ID

Something like:

var turkInfo = jsPsych.getTurkInfo();
// turkInfo then looks like:
// {preview: false, workerID: ASB1239582AB, HITID: 1233AFJI2, assignmentID: 954380GTMH}

Text plugin should auto wrap content in <p> tag if needed

For cleanest presentation with the default style sheet being built, the text plugin should automatically wrap the text input in <p> tags if they are not already there (or if there is not an outer HTML element).

A quick way to check might be to see if the first character of the string is '<'.

Or a more sophisticated check to see if there is a valid tag structure?

Divide core library into modules

There are several functions being added to the core library. To maintain an organizational structure that is easy to grasp, the core library should be extended via modules. Proposed modules are:

  • pluginAPI for functions that are helpful for plugin development, but are not generally used outside of plugin development.
  • turk for functions related to mechanical turk
  • randomization for functions that help randomize experimental designs
  • data for functions related to data collection.

CSS themes

Create CSS theme(s) that make default jsPsych content look nice.

Preferably, content should scale within reason, i.e. work across multiple screen resolutions.

block specific css classes

I recently ran into a scenario where I wanted to apply different CSS rules to the same plugin, when it was used to generate two different kinds of blocks in an experiment. It would be nice to be able to style blocks differently even if they use the same plugin.

One way to do this would be to add an optional parameter that attaches a style to all stimuli displayed by the block. This works for plugins where only one kind of stimulus is primarily used.

Allow trial variables to be functions

Variables can be passed in as functions. Functions are evaluated at the start of the trial, which allows for more dynamic options.

See branch function-variables.

Timeouts not clearing in jsPsych.similarity

Hi! I am working with your library to develop an experiment investigating the effects of category learning on similarity judgments at Pr. Stevan Harnad's lab at UQAM in Montreal. Our design requires that trials be limited to a fixed time limit, a feature I am currently implementing, and in the course of development I noticed the following bug in the similarity plugin:

Because the calls to setTimeout() are not cancelled when the anonymous function on line 201 is called, many functions try to be executed after a trial has ended. Calls on line 75, 84, and 105 are still scheduled, and thus happen at innapropriate times during the next trial. This causes erratic behavior. Notice that the sim_trial_complete flag isnt really useful as a fix for this, since it only protects from the call to line 105 during the inter trial period, and if, like me, you have none, then the flag is set to true by the next trial immediately.

In short, the code assumes that the subjects will only submit their answer after having seen both stimuli, and that timing_post_trial > timing_second_stim. As a fix, I propose to set handles to each call to setTimeout, and have the anonymous function that starts the next trial run cleartimeout() on all of them.

By the way, I would love to contribute to this open source project, as I think web experiments are very useful to increase participant pool and mitigate costs. If you are interested, I can also show you how I implemented my timeout feature.

Regards,
Daniel Rivas

Optional data object in IE

Hi,
I want to add an optional data object through the categorize plugin. This seems to work fine in all browsers, but when I run it live from the server suddenly IE(9) doesn't add it. Had a quick look through the plugin and jspsych.js but struggled to understand it (I'm new to javascript)! Any ideas?

similarity plugin adjustments

The similarity plugin should be adjusted in a few ways:

  • Use the code from the Likert plugin to add option to limit responses to a certain number of bins.
  • Allow labeling multiple points on the scale
  • Allow option to control when response slider appears.

Global trial index

Add global trial index to data object. Keeps track of trial number regardless of block.

Can be implemented in the core library, within writeData function.

Allow key values to be specified as numbers or characters

I think the best way to do this is to offer a function in the core library to normalize the values to the numeric representation.

Something like:

if(typeof key == 'number') { 
   return key;
} else if(typeof key == 'string') {
   // make letters uppercase first in order to get the right key

   var k = key.charCodeAt(0);
   return k;
} else {
  // give an error
}

automatic browser feature detection

In theory, jsPsych should be able to know if a browser is capable of running a particular experiment automatically.

Each plugin should have a custom feature detection routine to check for features that are relevant to that plugin. The core library can then have a method that runs the feature detection routines of all loaded plugins, so that all the programmer has to do is something like:

jsPsych.checkCompatibility()

More info here: http://learn.jquery.com/code-organization/feature-browser-detection/

Plugins have callback functions at end of trial

Using the on_data_update callback from the core library might be cumbersome if you want interaction that is specific to a particular plugin finishing, such as updating a state variable.

Callback includes data generated by trial

on_end_trial(data) {  }

This also requires changing docs on creating a new plugin and changing the plugin template

Default data for all plugins

The core library will record a set of 'default data' for each trial, which includes:

  • the trial type (which plugin was used)
  • the trial index within a block
  • the trial index in the global context

Plugins can be modified to stop recording these items locally, since the writeData method will handle it.

preload audio files

Since HTML5 supports a javascript Audio object, the preload images method can be applied almost as-is for audio files too. Once plugins start to use audio samples, this would be a good thing for the core library to support. Maybe even a generic preload() method that determines type and caches appropriately?

load experiment description from file

To really reduce the amount of code people have to write for simple experiments, it would be nice to have a way to load a complete experiment description from a file.

Could be a JSON string that describes the experiment?

Core library support for randomization

The core library could include some methods for randomization of order and such, since plugins don't support this.

A basic version would just be to include something like the underscore.js shuffle method.

More sophisticated options would be sample N from a list with and without replacement, etc..

Also, a common use case is to define a set of variables that go together:

var trials = [
     {param1: value, param2: value, param3: value},
     {param1: value, param2: value, param3: value},
     {param1: value, param2: value, param3: value}
];

But, plugins work by taking arrays of like parameters:

var plugin_block = { ..., param1: [value1, value2, value3], param2: [value1, value2, value3], ... }

So a useful randomization method would take an object like trials, shuffle the order, sample N times, and then return the needed arrays.

update categorize-animation plugin

Update this plugin to pull out of /dev and into main /plugins folder. Plugin is basically a mashup of animation and categorize plugins.

  • Make v1.6 compatible with writeData method, etc...
  • Update wiki with doc and example

same-diff plugin data naming

The same-diff plugin has the old style "a_path" and "b_path" labels for data generated. Too late to fix for v1.6, so fix it for the next release. Reverted wiki page to reflect the current data, but will need to change when this issue is addressed.

Conditional branching

The experiment_structure declaration could support conditional branching at some point. This would require a lot of changes to different aspects of the library, since the experiment structure would be created dynamically rather than statically. Aspects that depend on static experiment structure would break.

There's no specific implementation strategy planned yet. Feel free to use this issue to suggest possible methods.

new html-template plugin

  • Plugin should allow user to specify an external html document with arbitrary variables. When plugin is initialized, variables get replaced into the template.
  • Callback function should be triggered whenever the user continues off of the page.

update categorize-multi plugin

Get this plugin over into the main branch. Main goal of plugin is to have a categorization trial where the item can be categorized in multiple ways. It would be like showing someone a picture of a cucumber and asking both "Is it a fruit or vegetable?" and "Is it green or yellow?"

  • v1.6 compatible with writeData method.
  • Multi categorization should be flexible from 1 - N.
  • Update wiki with doc and example

Refactoring how trials are declared

When declaring a block of trials, it can be confusing to align all of the options, particularly when they require nested arrays. For example, the survey-likert plugin is particularly ugly:

// defining groups of questions that will go together.
        var page_1_questions = ["I like vegetables.", "I hate eggs."];
        var page_2_questions = ["I like fruit."];

        // definiting two different response scales that can be used.
        var scale_1 = ["Strongly Disagree", "Disagree", "Neutral", "Agree", "Strongly Agree"];
        var scale_2 = ["Strongly Disagree", "Disagree", "Somewhat Disagree", "Neural", "Somewhat Agree", "Agree", "Strongly Agree"];

        var likert_block = {
            type: 'survey-likert',
            questions: [page_1_questions, page_2_questions],
            labels: [[scale_1, scale_2], [scale_1]], // need one scale for every question on a page
            intervals: [[5,7], [9]] // note the the intervals and labels don't necessarily need to match.
        };

One solution would be an alternate form of declaring trials within the block. The block would simply accept an array of trials:

var trials_object = [{trial1}, {trial2}] //pseudocode

var block = {
   type: 'survey-likert',
   trials: trials_object
};

To specify a parameter, you can either do it at the trials_object level OR at the block level. If a parameter is specified at the trial level, it overrides the block level. You could even mix and match within a block, by having a default block level parameter, and then individual overrides for the trial.

Handle one-element arrays better in plugins

Plugins are designed to allow multiple trials without creating a new block for each trial, so many parameters are passed in as arrays. However, there are plenty of times where you really only want one trial with a block, and a common error is to leave out the array declaration. A good example is the text plugin.

var instructions = "<p>These are the experiment instructions</p>";

// this is a bad declaration because the text parameter is expecting an array
var instructions_block = {
   type: "text",
   text: instructions
}

// this is correct
var instructions_block = {
   type: "text",
   text: [instructions]
}

It would be great to have some smart error handling in this case. If there is a parameter that should be an array, but a non-array is passed in, then it should be assumed that it is a single element.

new audio plugin

Everything in the library is visual right now, but audio support in JavaScript / HTML5 is not bad.

A basic audio + response plugin would be a nice addition to the library. It can follow the basic template of the single-stim plugin:

  1. Present audio clip to subject.
  2. Allow response with set of keys.

rt should be measured on key down

Having rt measured on keyup introduces unnecessary noise based on how long it takes people to release the key. Changing to keydown is better.

keydown / up detection

RT measurements are based on keydown (See #17), but this opens the possibility of someone holding down the key and quickly advancing through multiple trials.

Perhaps there is a more complicated compromise where rt is measured from keydown, but keyup is required to advance the trial.

Plugins should handle timing_post_trial values of 0

Right now, most plugins will call setTimeout with a timeout value of 0, which leads to strange behavior. When a timing_post_trial value of 0 is requested, the plugin should skip setting a setTimeout method, and instead call block.next() immediately.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.