diff --git a/README.md b/README.md index 80af9e7c..35bdc8fe 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@  -jsPsych is a JavaScript library for creating and running behavioral experiments in a web browser. jsPsych simplifies the process of coding browser-based experiments by providing a set of flexible plugins that define different kinds of tasks a subject could complete during an experiment. By assembling different plugins together and customizing the parameters of each, it is possible to create many different types of experiments. +jsPsych is a JavaScript library for creating behavioral experiments that run in a web browser. jsPsych creates a framework for defining experiments and provides a set of flexible plugins that create different kinds of tasks a subject could complete during an experiment. By assembling different plugins together and customizing the parameters of each, it is possible to create many different types of experiments. Documentation ------------- @@ -27,10 +27,10 @@ de Leeuw, J.R. (2015). jsPsych: A JavaScript library for creating behavioral exp Response times -------------- -Wondering if jsPsych can be used for research that depends on accurate response time measurement? In general, the answer is yes. Response time measurements in jsPsych (and JavaScript in general) are comparable to those taken in standard lab software like Psychophysics Toolbox and E-Prime. Response times measured in JavaScript tend to be a little bit longer (10-40ms), but have similar variance. See the following references for extensive work on this topic. +Wondering if jsPsych can be used for research that depends on accurate response time measurement? For most purposes, the answer is yes. Response time measurements in jsPsych (and JavaScript in general) are comparable to those taken in standard lab software like Psychophysics Toolbox and E-Prime. Response times measured in JavaScript tend to be a little bit longer (10-40ms), but have similar variance. See the following references for extensive work on this topic. * [de Leeuw, J. R., & Motz, B. A. (2016). Psychophysics in a Web browser? Comparing response times collected with JavaScript and Psychophysics Toolbox in a visual search task. *Behavior Research Methods*, *48*(1), 1-12.](http://link.springer.com/article/10.3758%2Fs13428-015-0567-2) -* [Hilbig, B. E. (in press). Reaction time effects in lab- versus web-based research: Experimental evidence. *Behavior Research Methods*.](http://dx.doi.org/10.3758/s13428-015-0678-9) +* [Hilbig, B. E. (2016). Reaction time effects in lab- versus web-based research: Experimental evidence. *Behavior Research Methods*, *48*(4), 1718-1724.](http://dx.doi.org/10.3758/s13428-015-0678-9) * [Pinet, S., Zielinski, C., Mathôt, S. et al. (in press). Measuring sequences of keystrokes with jsPsych: Reliability of response times and interkeystroke intervals. *Behavior Research Methods*.](http://link.springer.com/article/10.3758/s13428-016-0776-3) * [Reimers, S., & Stewart, N. (2015). Presentation and response time accuracy in Adobe Flash and HTML5/JavaScript Web experiments. *Behavior Research Methods*, *47*(2), 309-327.](http://link.springer.com/article/10.3758%2Fs13428-014-0471-1) diff --git a/contributors.md b/contributors.md index 1828c803..c57235c6 100644 --- a/contributors.md +++ b/contributors.md @@ -1,11 +1,16 @@ -The following people have contributed to the development of jsPsych by writing code, documentation, and/or suggesting major improvements (in alphabetical order): +The following people have contributed to the development of jsPsych by writing code, documentation, and/or suggesting improvements (in alphabetical order): +* Xiaolu Bai - https://github.com/lbai001 * Jason Carpenter -* Josh de Leeuw - https://github.com/jodeleeuw +* Steve Chao - https://github.com/stchao * Jana Klaus - https://github.com/janakl4us * Jonas Lambers * Shane Martin - https://github.com/shamrt * Adrian Oesch - https://github.com/adrianoesch * Junyan Qi - https://github.com/GavinQ1 +* Dan Rivas - https://github.com/rivasd * Marian Sauter - https://github.com/mariansauter * Tim Vergenz - https://github.com/vergenzt +* Matteo Visconti di Oleggio Castello - https://github.com/mvdoc +* Wolfgang Walther - https://github.com/wolfgangwalther * Erik Weitnauer - https://github.com/eweitnauer +* Rob Wilkinson - https://github.com/RobAWilkinson diff --git a/css/jspsych.css b/css/jspsych.css index 5d533a5a..6cd03b62 100644 --- a/css/jspsych.css +++ b/css/jspsych.css @@ -62,7 +62,7 @@ input[type="text"] { .jspsych-btn { display: inline-block; padding: 6px 12px; - margin: 0px 8px; + margin: 0px; font-size: 14px; font-weight: 400; font-family: 'Open Sans', 'Arial', sans-serif; @@ -98,7 +98,6 @@ input[type="text"] { #jspsych-progressbar-outer { background-color: #dedede; border-radius: 5px; - padding: 1px; width: 800px; margin: auto; } diff --git a/docs/markdown_docs/core_library/jspsych-core.md b/docs/markdown_docs/core_library/jspsych-core.md index 482e8818..3569db98 100644 --- a/docs/markdown_docs/core_library/jspsych-core.md +++ b/docs/markdown_docs/core_library/jspsych-core.md @@ -306,7 +306,6 @@ show_progress_bar | boolean | If true, then [a progress bar](../features/progres preload_audio | array | An array of audio files to preload before starting the experiment. preload_images | array | An array of image files to preload before starting the experiment. max_load_time | numeric | The maximum number of milliseconds to wait for content to preload. If the wait time is exceeded an error message is displayed and the experiment stops. The default value is 60 seconds. -fullscreen | boolean | If true, the experiment will run in fullscreen mode. See the [feature page](../features/fullscreen.md) for more details. default_iti | numeric | The default inter-trial interval in ms. The default value if none is specified is 0ms. Possible values for the exclusions parameter above. diff --git a/docs/markdown_docs/features/data.md b/docs/markdown_docs/features/data.md index 532c7e76..b6da7430 100644 --- a/docs/markdown_docs/features/data.md +++ b/docs/markdown_docs/features/data.md @@ -15,8 +15,8 @@ In most cases, data collection will be automatic and hidden. Plugins save data o Often it is useful to add a piece of data to *all* of the trials in the experiment. For example, appending the subject ID to each trial. This can be done with the `jsPsych.data.addProperties()` function. Here is an example: ```javascript -// generate a random subject ID -var subject_id = Math.floor(Math.random()*100000); +// generate a random subject ID with 15 characters +var subject_id = jsPsych.randomization.randomID(15); // pick a random condition for the subject at the start of the experiment var condition_assignment = jsPsych.randomization.sample(['conditionA', 'conditionB', 'conditionC'],1)[0]; @@ -143,28 +143,121 @@ The `file_put_contents($filename, $data)` method requires permission to write ne To use the PHP script, the JavaScript that runs jsPsych needs to send the `filename` and `filedata` information. This is done through an [AJAX](http://www.w3schools.com/xml/ajax_intro.asp) call. ```javascript -function saveData(filename, filedata){ - $.ajax({ - type:'post', - cache: false, - url: 'save_data.php', // this is the path to the above PHP script - data: {filename: filename, filedata: filedata} - }); +function saveData(name, data){ + var xhr = new XMLHttpRequest(); + xhr.open('POST', 'write_data.php'); // 'write_data.php' is the path to the php file described above. + xhr.setRequestHeader('Content-Type', 'application/json'); + xhr.send(JSON.stringify({filename: filename, filedata: filedata})); } // call the saveData function after the experiment is over jsPsych.init({ - // code to define the experiment structure would go here... - - on_finish: function(data){ saveData("filename.csv", jsPsych.data.getDataAsCSV()) } + on_finish: function(){ saveData("experiment_data.csv", jsPsych.data.get().csv()); } }); ``` -To use this in an actual experiment, it would be important to tie the filename to some unique identifier like a subject number. +To use this in an actual experiment, it would be important to tie the filename to some unique identifier like a subject number. Otherwise the file may be overwritten by collecting new data. ## Storing data permanently in a MySQL database The ideal solution for storing data generated by jsPsych is to write it to a database. -There are dozens of database options. MySQL is one of the most popular [relational databases](http://en.wikipedia.org/wiki/Relational_database), is free to use, and relatively easy [to install](https://www.google.com/search?q=how+to+install+mysql). This page will assume that you have a MySQL database installed on your server that is hosting the jsPsych experiment, and that your server is able to execute PHP code. If you are trying to run on a local machine, you'll need to install a local server environment like [XAMPP](https://www.apachefriends.org/index.html). +There are dozens of database options. MySQL is one of the most popular [relational databases](http://en.wikipedia.org/wiki/Relational_database), is free to use, and relatively easy [to install](https://www.google.com/search?q=how+to+install+mysql). This code will assume that you have a MySQL database installed on your server that is hosting the jsPsych experiment, and that your server is able to execute PHP code. If you are trying to run on a local machine, you'll need to install a local server environment like [XAMPP](https://www.apachefriends.org/index.html). + +You'll need two PHP scripts. The first is a configuration file for your database. Save it as `database_config.php` on your server. Within this file are configuration options for the database. You'll need to change these according to how you have configured your MySQL installation. + +```php + +``` + +The second PHP file will write data to the database. This script reads the database to discover what columns are in the table, and then only allows data to be entered in that matches those columns. This is a security feature. Save this file as `write_data.php` on your server. + +```php +setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + // First stage is to get all column names from the table and store + // them in $col_names array. + $stmt = $conn->prepare("SHOW COLUMNS FROM `$table`"); + $stmt->execute(); + $col_names = array(); + while($row = $stmt->fetchColumn()) { + $col_names[] = $row; + } + // Second stage is to create prepared SQL statement using the column + // names as a guide to what values might be in the JSON. + // If a value is missing from a particular trial, then NULL is inserted + $sql = "INSERT INTO $table VALUES("; + for($i = 0; $i < count($col_names); $i++){ + $name = $col_names[$i]; + $sql .= ":$name"; + if($i != count($col_names)-1){ + $sql .= ", "; + } + } + $sql .= ");"; + $insertstmt = $conn->prepare($sql); + for($i=0; $i < count($data_array); $i++){ + for($j = 0; $j < count($col_names); $j++){ + $colname = $col_names[$j]; + if(!isset($data_array[$i][$colname])){ + $insertstmt->bindValue(":$colname", null, PDO::PARAM_NULL); + } else { + $insertstmt->bindValue(":$colname", $data_array[$i][$colname]); + } + } + $insertstmt->execute(); + } + echo '{"success": true}'; +} catch(PDOException $e) { + echo '{"success": false, "message": ' . $e->getMessage(); +} +$conn = null; +?> +``` + +To send the data, we use an AJAX request in JavaScript. +```JavaScript +function saveData() { + var xhr = new XMLHttpRequest(); + xhr.open('POST', 'write_data.php'); // change 'write_data.php' to point to php script. + xhr.setRequestHeader('Content-Type', 'application/json'); + xhr.onload = function() { + if(xhr.status == 200){ + var response = JSON.parse(xhr.responseText); + console.log(response.success); + } + }; + xhr.send(jsPsych.data.getData().json()); +} +``` + +You can call the `saveData()` function using the `on_finish` handler for the experiment, or by using the `call-function` plugin. + +```javascript +// with on_finish handler +jsPsych.init({ + on_finish: saveData +}); + +// with call-function plugin +timeline.push({ + type: 'call-function', + func: saveData +}); +``` diff --git a/docs/markdown_docs/features/fullscreen.md b/docs/markdown_docs/features/fullscreen.md index 5e308d01..9f4a944f 100644 --- a/docs/markdown_docs/features/fullscreen.md +++ b/docs/markdown_docs/features/fullscreen.md @@ -1,14 +1,36 @@ # Fullscreen Experiments -You can run your experiment in fullscreen mode by setting the `fullscreen` parameter in the `jsPsych.init` call that launches the experiment. +You can run your experiment in fullscreen mode by using the jspsych-fullscreen plugin. ```javascript +var timeline = []; + +timeline.push({ + type: 'fullscreen', + fullscreen_mode: true +}); + +timeline.push({ + type: 'text', + text: 'This trial will be in fullscreen mode.' +}); + +// exit fullscreen mode +timeline.push({ + type: 'fullscreen', + fullscreen_mode: false +}); + +timeline.push({ + type: 'text', + text: 'This trial will NOT be in fullscreen mode.' +}); + jsPsych.init({ - timeline: timeline, - fullscreen: true + timeline: timeline }); ``` -For security reasons, launching the browser into fullscreen mode requires that the user take an action. Therefore, if fullscreen mode is requested, a button will be displayed on the page to launch the experiment into fullscreen mode. The experiment will not begin until this button is pressed. +For security reasons, web browsers require that users initiate an action to launch fullscreen mode. The fullscreen plugin displays a button that the user must click to change the display to fullscreen. -Safari does not support keyboard input when the browser is in fullscreen mode. Therefore, the function will not launch fullscreen mode on Safari. +Safari does not support keyboard input when the browser is in fullscreen mode. Therefore, the function will not launch fullscreen mode on Safari. The experiment will ignore any trials using the fullscreen plugin in Safari. diff --git a/docs/markdown_docs/features/media-preloading.md b/docs/markdown_docs/features/media-preloading.md index 836936ea..b14e3399 100644 --- a/docs/markdown_docs/features/media-preloading.md +++ b/docs/markdown_docs/features/media-preloading.md @@ -47,8 +47,8 @@ var audio = ['audio/foo.mp3']; jsPsych.init({ timeline: [trial], - audio_preload: audio, - image_preload: images + preload_audio: audio, + preload_images: images }); ``` diff --git a/docs/markdown_docs/plugins/jspsych-resize.md b/docs/markdown_docs/plugins/jspsych-resize.md new file mode 100644 index 00000000..d8b05d7c --- /dev/null +++ b/docs/markdown_docs/plugins/jspsych-resize.md @@ -0,0 +1,30 @@ +# jspsych-resize + +This plugin displays a resizable div container that allows the user to drag until the container is the same size as the item being measured. Once the user measures the item as close as possible, clicking the button sets a scaling factor for the div containing jsPsych content. This causes the stimuli that follow to have a known size, independent of monitor resolution. + +## Parameters + +This table lists the parameters associated with this plugin. Parameters with a default value of *undefined* must be specified. Other parameters can be left unspecified if the default value is acceptable. + +Parameter | Type | Default Value | Description +----------|------|---------------|------------ +item_height | numeric | 1 | The height of the item to be measured. Any units can be used as long as you are consistent with using the same units for all parameters. +item_width | numeric | 1 | The width of the item to be measured. +pixels_per_unit | numeric | 100 | After the scaling factor is applied, this many pixels will equal one unit of measurement. +prompt | string | `''` | HTML content to display below the resizable box, and above the button. +button_text | string | `'Done'` | Label to display on the button to complete calibration. +starting_size | numeric | 100 | The initial size of the box, in pixels, along the largest dimension. The aspect ratio will be set automatically to match the item width and height. + +## Examples + +#### Measuring a credit card and resizing the display to have 150 pixels equal an inch. + +```javascript +var inputs = { + type: 'resize', + item_width: 3 + 3/8, + item_height: 2 + 1/8, + prompt: "
Click and drag the lower right corner of the box until the box is the same size as a credit card held up to the screen.
", + pixels_per_unit: 150 +}; +``` diff --git a/docs/markdown_docs/plugins/jspsych-survey-multi-picture.md b/docs/markdown_docs/plugins/jspsych-survey-multi-picture.md new file mode 100644 index 00000000..a499c6b1 --- /dev/null +++ b/docs/markdown_docs/plugins/jspsych-survey-multi-picture.md @@ -0,0 +1,56 @@ +# jspsych-survey-multi-picture plugin + +The survey-multi-picture plugin displays a set of questions with multiple picture response fields. The subject selects a single answer. + +## Parameters + +This table lists the parameters associated with this plugin. Parameters with a default value of *undefined* must be specified. Other parameters can be left unspecified if the default value is acceptable. + +Parameter | Type | Default Value | Description +----------|------|---------------|------------ +questions | array | *undefined* | An array of strings. The strings are the prompts/questions that will be associated with a group of options (images). All questions will get presented on the same page (trial). +options | array | *undefined* | An array of arrays of objects containing url key and label key(label is optional). The innermost arrays contain a set of options to display for an individual question. The length of the outer array should be the same as the number of questions. +horizontal | boolean | false | If true, then questions are centered and options are displayed horizontally. +preamble | string | empty string | HTML formatted string to display at the top of the page above all the questions. + +## Data Generated + +In addition to the [default data collected by all plugins](overview#datacollectedbyplugins), this plugin collects the following data for each trial. + +Name | Type | Value +-----|------|------ +responses | JSON string | A string in JSON format containing the response for each question. The encoded object will have a separate variable for the response to each question, with the first question in the trial being recorded in `Q0`, the second in `Q1`, and so on. The responses are recorded as the image url for the picture clicked on. +rt | numeric | The response time in milliseconds for the subject to make a response. The time is measured from when the questions first appear on the screen until the subject's response. + +## Examples + +#### Basic example with multiple questions on a page. + +```javascript + // defining groups of questions that will go together. + var page_1_questions = ["I like vegetables.", "I like fruit."]; + + // definiting two different response scales that can be used. + var page_1_options = [{url: "http://www.thetechconnectioninc.com/assets/img/Twitter.png", label: "twitter"}, {url: "http://www.freeiconspng.com/uploads/facebook-logo-png-20.png", label: "facebook"}]; + var page_2_options = [{url: "http://www.gameswithwords.org/WhichEnglish/images/1_1.jpg", label: "dog chase cat"}, {url: "http://www.gameswithwords.org/WhichEnglish/images/1_2.jpg", label: "cat chase dog"}]; + + var multi_picture_block = { + type: 'survey-multi-picture', + questions: page_1_questions, + options: [page_1_options, page_2_options], // need one scale for every question on a page + }; + + var multi_picture_block_horizontal = { + type: 'survey-multi-picture', + questions: page_1_questions, + options: [page_1_options, page_2_options], // need one scale for every question on a page + horizontal: true // centers questions and makes options display horizontally + }; + + jsPsych.init({ + timeline: [multi_picture_block, multi_picture_block_horizontal], + on_finish: function() { + jsPsych.data.displayData(); + } + }); +``` diff --git a/docs/markdown_docs/plugins/jspsych-survey-multi-select.md b/docs/markdown_docs/plugins/jspsych-survey-multi-select.md new file mode 100644 index 00000000..82d7899a --- /dev/null +++ b/docs/markdown_docs/plugins/jspsych-survey-multi-select.md @@ -0,0 +1,58 @@ +# jspsych-survey-multi-select plugin + +The survey-multi-select plugin displays a set of questions with multiple select response fields. The subject could select multiple answers. + +## Parameters + +This table lists the parameters associated with this plugin. Parameters with a default value of *undefined* must be specified. Other parameters can be left unspecified if the default value is acceptable. + +Parameter | Type | Default Value | Description +----------|------|---------------|------------ +questions | array | *undefined* | An array of strings. The strings are the prompts/questions that will be associated with a group of options (check boxes). All questions will get presented on the same page (trial). +options | array | *undefined* | An array of arrays. The innermost arrays contain a set of options to display for an individual question. The length of the outer array should be the same as the number of questions. +required | boolean | true | If true, then at least one option must be selected. +required_msg | string | `*please select at least one option!` | Message to display if required check is not met. +horizontal | boolean | false | If true, then questions are centered and options are displayed horizontally. +preamble | string | empty string | HTML formatted string to display at the top of the page above all the questions. + +## Data Generated + +In addition to the [default data collected by all plugins](overview#datacollectedbyplugins), this plugin collects the following data for each trial. + +Name | Type | Value +-----|------|------ +responses | JSON string | An array containing all selected choices in JSON format for each question. The encoded object will have a separate variable for the response to each question, with the first question in the trial being recorded in `Q0`, the second in `Q1`, and so on. The responses are recorded as the name of the option label. +rt | numeric | The response time in milliseconds for the subject to make a response. The time is measured from when the questions first appear on the screen until the subject's response. + +## Examples + +#### Basic example with multiple questions on a page. + +```javascript + // defining groups of questions that will go together. + var page_1_questions = ["I like vegetables.", "I like fruit."]; + + // definiting two different response scales that can be used. + var page_1_options = ["Strongly Disagree", "Disagree", "Neutral", "Agree", "Strongly Agree"]; + var page_2_options = ["Strongly Disagree", "Disagree", "Somewhat Disagree", "Neural", "Somewhat Agree", "Agree", "Strongly Agree"]; + + var multi_select_block = { + type: 'survey-multi-select', + questions: page_1_questions, + options: [page_1_options, page_2_options], // need one scale for every question on a page + }; + + var multi_select_block_horizontal = { + type: 'survey-multi-select', + questions: page_1_questions, + options: [page_1_options, page_2_options], // need one scale for every question on a page + horizontal: true // centers questions and makes options display horizontally + }; + + jsPsych.init({ + timeline: [multi_select_block, multi_select_block_horizontal], + on_finish: function() { + jsPsych.data.displayData(); + } + }); +``` diff --git a/docs/markdown_docs/plugins/jspsych-video.md b/docs/markdown_docs/plugins/jspsych-video.md index fb29f64d..b4291dec 100644 --- a/docs/markdown_docs/plugins/jspsych-video.md +++ b/docs/markdown_docs/plugins/jspsych-video.md @@ -14,6 +14,8 @@ height | numeric | heigh of the video file | The height of the video display in prompt | string | empty string | A message (any valid HTML) to display beneath the video element. autoplay | boolean | true | If true, the video will begin playing as soon as it has loaded. controls | boolean | false | If true, controls for the video player will be available to the subject. They will be able to pause the video or move the playback to any point in the video. +start | numeric | 0 | If given a value, the video will start at this time point in seconds. +stop| numeric | *undefined* | If given a value, the video will stop at this time point in seconds. ## Data Generated diff --git a/docs/markdown_docs/plugins/overview.md b/docs/markdown_docs/plugins/overview.md index 402bbd91..7f837a1e 100644 --- a/docs/markdown_docs/plugins/overview.md +++ b/docs/markdown_docs/plugins/overview.md @@ -75,7 +75,8 @@ This table is a description of all plugins that are currently bundled with jsPsy [jspsych‑instructions](jspsych-instructions) | For displaying instructions to the subject. [jspsych‑multi‑stim‑multi‑response](jspsych-multi-stim-multi-response) | A more generalized version of the single-stim plugin. Can display multiple stimuli in a single trial, and collect multiple responses in a single trial. [jspsych‑palmer](jspsych-palmer) | Shows grid-like stimuli inspired by Stephen Palmer's work. The stimuli are editable: subjects can add and subtract parts interactively. Also contains a method for generating the HTML code to render the stimuli, allowing them to be used in other plugins. - [jspsych‑reconstruction](jspsych-reconstruction) | The subject interacts with a stimulus by modifying a parameter of the stimulus and observing the change in the stimulus in real-time. + [jspsych‑reconstruction](jspsych-reconstruction) | The subject interacts with a stimulus by modifying a parameter of the stimulus and observing the change in the stimulus in real-time. + [jspsych‑resize](jspsych-resize) | Calibrate the display so that materials display with a known physical size. [jspsych‑same‑different](jspsych-same-different) | A same-different judgment task. A stimulus is shown, followed by a brief gap, and then another stimulus is shown. The subject indicates whether the stimuli are the same or different. [jspsych‑similarity](jspsych-similarity) | Two stimuli are shown sequentially, and the subject indicates how similar they are by dragging a slider object. [jspsych‑single‑audio](jspsych-single-audio) | A basic plugin for playing an audio stimulus and getting a keyboard response. diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index 6a223683..89cdcf2e 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -46,6 +46,7 @@ pages: - 'jspsych-multi-stim-multi-response': 'plugins/jspsych-multi-stim-multi-response.md' - 'jspsych-palmer': 'plugins/jspsych-palmer.md' - 'jspsych-reconstruction': 'plugins/jspsych-reconstruction.md' + - 'jspsych-resize': 'plugins/jspsych-resize.md' - 'jspsych-same-different': 'plugins/jspsych-same-different.md' - 'jspsych-similarity': 'plugins/jspsych-similarity.md' - 'jspsych-single-audio': 'plugins/jspsych-single-audio.md' diff --git a/examples/demo-simple-rt-task.html b/examples/demo-simple-rt-task.html index f9bcccf4..babd629e 100644 --- a/examples/demo-simple-rt-task.html +++ b/examples/demo-simple-rt-task.html @@ -14,7 +14,7 @@ var timeline = []; /* define welcome message trial */ - var welcome = { + var welcome_block = { type: "text", text: "Welcome to the experiment. Press any key to begin." }; diff --git a/examples/flex-layout-testing.html b/examples/flex-layout-testing.html new file mode 100644 index 00000000..0b088826 --- /dev/null +++ b/examples/flex-layout-testing.html @@ -0,0 +1,30 @@ + + + + + + + + + + diff --git a/examples/jspsych-fullscreen.html b/examples/jspsych-fullscreen.html new file mode 100644 index 00000000..171fdc2e --- /dev/null +++ b/examples/jspsych-fullscreen.html @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + diff --git a/examples/jspsych-resize.html b/examples/jspsych-resize.html new file mode 100644 index 00000000..2b8bf251 --- /dev/null +++ b/examples/jspsych-resize.html @@ -0,0 +1,34 @@ + + + + + + + + + + + + diff --git a/examples/jspsych-survey-likert.html b/examples/jspsych-survey-likert.html index 7c43acee..8441c0cc 100644 --- a/examples/jspsych-survey-likert.html +++ b/examples/jspsych-survey-likert.html @@ -1,7 +1,7 @@ - + @@ -18,6 +18,7 @@ var likert_block = { type: 'survey-likert', questions: ["I like vegetables.", "I like fruit."], + required: true, labels: [scale_1, scale_1], // need one scale for every question on a page }; diff --git a/examples/jspsych-survey-multi-picture.html b/examples/jspsych-survey-multi-picture.html new file mode 100644 index 00000000..c4fff1e7 --- /dev/null +++ b/examples/jspsych-survey-multi-picture.html @@ -0,0 +1,31 @@ + + + + +The experiment will switch to full screen mode when you press the button below
', + array: false, + no_function: false, + description: '' + }, + button_label: { + type: [jsPsych.plugins.parameterType.STRING], + default: "Go", + array: false, + no_function: false, + description: '' + }, + delay_after: { + type: [jsPsych.plugins.parameterType.INT], + default: 1000, + array: false, + no_function: false, + description: '' + }, + } + } + + plugin.trial = function(display_element, trial) { + + trial.fullscreen_mode = typeof trial.fullscreen_mode === 'undefined' ? true : trial.fullscreen_mode; + trial.message = trial.message || 'The experiment will switch to full screen mode when you press the button below
'; + trial.button_label = trial.button_label || 'Go'; + trial.delay_after = trial.delay_after || 1000; + + // if any trial variables are functions + // this evaluates the function and replaces + // it with the output of the function + trial = jsPsych.pluginAPI.evaluateFunctionParameters(trial); + + // check if keys are allowed in fullscreen mode + var keyboardNotAllowed = typeof Element !== 'undefined' && 'ALLOW_KEYBOARD_INPUT' in Element; + if (keyboardNotAllowed) { + // This is Safari, and keyboard events will be disabled. Don't allow fullscreen here. + // do something else? + endTrial(); + } else { + if(trial.fullscreen_mode){ + display_element.innerHTML = trial.message + ''; + var listener = display_element.querySelector('#jspsych-fullscreen-btn').addEventListener('click', function() { + var element = document.documentElement; + if (element.requestFullscreen) { + element.requestFullscreen(); + } else if (element.mozRequestFullScreen) { + element.mozRequestFullScreen(); + } else if (element.webkitRequestFullscreen) { + element.webkitRequestFullscreen(); + } else if (element.msRequestFullscreen) { + element.msRequestFullscreen(); + } + endTrial(); + }); + } else { + if (document.exitFullscreen) { + document.exitFullscreen(); + } else if (document.msExitFullscreen) { + document.msExitFullscreen(); + } else if (document.mozCancelFullScreen) { + document.mozCancelFullScreen(); + } else if (document.webkitExitFullscreen) { + document.webkitExitFullscreen(); + } + endTrial(); + } + } + + function endTrial() { + + display_element.innerHTML = ''; + + jsPsych.pluginAPI.setTimeout(function(){ + + var trial_data = { + success: !keyboardNotAllowed + }; + + jsPsych.finishTrial(trial_data); + + }, trial.delay_after); + + } + + }; + + return plugin; +})(); diff --git a/plugins/jspsych-instructions.js b/plugins/jspsych-instructions.js index c889fcfe..80d39e5c 100644 --- a/plugins/jspsych-instructions.js +++ b/plugins/jspsych-instructions.js @@ -53,6 +53,18 @@ jsPsych.plugins.instructions = (function() { default: false, no_function: false, description: '' + }, + button_label_previous: { + type: [jsPsych.plugins.parameterType.STRING], + default: 'Previous', + no_function: false, + description: '' + }, + button_label_next: { + type: [jsPsych.plugins.parameterType.STRING], + default: 'Next', + no_function: false, + description: '' } } } @@ -64,6 +76,8 @@ jsPsych.plugins.instructions = (function() { trial.allow_backward = (typeof trial.allow_backward === 'undefined') ? true : trial.allow_backward; trial.allow_keys = (typeof trial.allow_keys === 'undefined') ? true : trial.allow_keys; trial.show_clickable_nav = (typeof trial.show_clickable_nav === 'undefined') ? false : trial.show_clickable_nav; + trial.button_label_previous = (typeof trial.button_label_previous === 'undefined') ? 'Previous' : trial.button_label_previous; + trial.button_label_next = (typeof trial.button_label_next === 'undefined') ? 'Next' : trial.button_label_next; // if any trial variables are functions // this evaluates the function and replaces @@ -78,6 +92,16 @@ jsPsych.plugins.instructions = (function() { var last_page_update_time = start_time; + function btnListener(evt){ + evt.target.removeEventListener('click', btnListener); + if(this.id === "jspsych-instructions-back"){ + back(); + } + else if(this.id === 'jspsych-instructions-next'){ + next(); + } + } + function show_current_page() { display_element.innerHTML = trial.pages[current_page]; @@ -85,50 +109,41 @@ jsPsych.plugins.instructions = (function() { var nav_html = "