├── img ├── black.png ├── blue.png ├── green.png ├── red.png ├── white.png ├── circle.png ├── orange.png ├── purple.png ├── redgrid.png ├── square.png ├── yellow.png ├── blackbox.png ├── whitebox.png ├── whitegrid.png ├── instructions.png ├── symm_instructions.png ├── symmetrySpanExampleGrid.png └── symmetrySpanExampleRecall.png ├── save_data.php ├── jspsych-6.0.4 ├── license.txt ├── css │ ├── jspsych_visualarray.css │ ├── jspsych_digitspan.css │ ├── jspsych_operationspan.css │ └── jspsych_grid.css ├── plugins │ ├── jspsych-spatial-span.js │ ├── jspsych-fullscreen.js │ ├── jspsych-html-keyboard-response.js │ ├── jspsych-survey-text.js │ ├── jspsych-digit-span-recall.js │ ├── jspsych-operation-span-recall.js │ ├── jspsych-html-button-operationspan.js │ ├── jspsych-spatial-span-recall.js │ ├── jspsych-visual-array-response.js │ ├── jspsych-instructions.js │ ├── jspsych-visual-array.js │ ├── jspsych-symmetry-judgement-task.js │ └── jspsych-visual-array-stimuli.js └── README.md ├── data └── WM_digit_span_sample_results.csv ├── README.md ├── visual_array_task.html ├── digit_span_task.html ├── symmetry_span_task.html └── operation_span_task.html /img/black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mahiluthra/working_memory_tests/HEAD/img/black.png -------------------------------------------------------------------------------- /img/blue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mahiluthra/working_memory_tests/HEAD/img/blue.png -------------------------------------------------------------------------------- /img/green.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mahiluthra/working_memory_tests/HEAD/img/green.png -------------------------------------------------------------------------------- /img/red.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mahiluthra/working_memory_tests/HEAD/img/red.png -------------------------------------------------------------------------------- /img/white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mahiluthra/working_memory_tests/HEAD/img/white.png -------------------------------------------------------------------------------- /img/circle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mahiluthra/working_memory_tests/HEAD/img/circle.png -------------------------------------------------------------------------------- /img/orange.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mahiluthra/working_memory_tests/HEAD/img/orange.png -------------------------------------------------------------------------------- /img/purple.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mahiluthra/working_memory_tests/HEAD/img/purple.png -------------------------------------------------------------------------------- /img/redgrid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mahiluthra/working_memory_tests/HEAD/img/redgrid.png -------------------------------------------------------------------------------- /img/square.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mahiluthra/working_memory_tests/HEAD/img/square.png -------------------------------------------------------------------------------- /img/yellow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mahiluthra/working_memory_tests/HEAD/img/yellow.png -------------------------------------------------------------------------------- /img/blackbox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mahiluthra/working_memory_tests/HEAD/img/blackbox.png -------------------------------------------------------------------------------- /img/whitebox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mahiluthra/working_memory_tests/HEAD/img/whitebox.png -------------------------------------------------------------------------------- /img/whitegrid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mahiluthra/working_memory_tests/HEAD/img/whitegrid.png -------------------------------------------------------------------------------- /img/instructions.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mahiluthra/working_memory_tests/HEAD/img/instructions.png -------------------------------------------------------------------------------- /img/symm_instructions.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mahiluthra/working_memory_tests/HEAD/img/symm_instructions.png -------------------------------------------------------------------------------- /img/symmetrySpanExampleGrid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mahiluthra/working_memory_tests/HEAD/img/symmetrySpanExampleGrid.png -------------------------------------------------------------------------------- /img/symmetrySpanExampleRecall.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mahiluthra/working_memory_tests/HEAD/img/symmetrySpanExampleRecall.png -------------------------------------------------------------------------------- /save_data.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /jspsych-6.0.4/license.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014-2018 Joshua R. de Leeuw 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /data/WM_digit_span_sample_results.csv: -------------------------------------------------------------------------------- 1 | "rt","recall","stimuli","accuracy","trial_type","trial_index","time_elapsed","internal_node_id" 2 | "2257","8,7,6","8,7,6","1","digit-span-recall","6","778644","0.0-3.0-1.0" 3 | "2961","4,1,7,0","4,1,7,0","1","digit-span-recall","12","786620","0.0-3.0-1.1" 4 | "2880","2,3,5,6,0","2,3,5,6,0","1","digit-span-recall","19","795516","0.0-3.0-1.2" 5 | "3612","4,1,0","4,1,0","1","digit-span-recall","25","803900","0.0-5.0-1.0" 6 | "6067","2,3,6,4","2,3,6,4","1","digit-span-recall","31","814987","0.0-5.0-1.1" 7 | "6255","7,6,5,3,0","7,6,5,3,0","1","digit-span-recall","38","827259","0.0-5.0-1.2" 8 | "9273","4,9,8,6,5,2","4,9,8,6,5,2","1","digit-span-recall","46","843555","0.0-5.0-1.3" 9 | "4360","5,3,9,4,6,8,2","5,3,9,6,4,8,2","0","digit-span-recall","55","855939","0.0-5.0-1.4" 10 | "5468","0,7,9,4,3,5,0","0,7,9,4,3,5,6","0","digit-span-recall","64","869427","0.0-5.0-1.5" 11 | "11158","7,9,2,5,3,1","7,9,2,5,3,1","1","digit-span-recall","72","887611","0.0-5.0-1.6" 12 | "5969","9,8,0,4,6,5,2","9,8,0,4,6,5,2","1","digit-span-recall","81","901603","0.0-5.0-1.7" 13 | "6771","4,7,8,6,9,2","7,1,8,4,6,9,0,2","0","digit-span-recall","91","917403","0.0-5.0-1.8" 14 | "6545","7,9,4,0,8,9,4,6","0,8,4,7,1,9,5,6","0","digit-span-recall","101","932987","0.0-5.0-1.9" 15 | "7448","1,8,7,0,9,4,1","1,8,7,2,0,4,9","0","digit-span-recall","110","948459","0.0-5.0-1.10" 16 | "4351","0,3,1,6,5","0,3,1,4,6,5","0","digit-span-recall","118","959827","0.0-5.0-1.11" 17 | "3703","4,2,5,6,9","4,2,5,6,9","1","digit-span-recall","125","969546","0.0-5.0-1.12" 18 | "8602","5,3,0,1,7,8","5,3,0,1,7,8","1","digit-span-recall","133","985170","0.0-5.0-1.13" 19 | -------------------------------------------------------------------------------- /jspsych-6.0.4/css/jspsych_visualarray.css: -------------------------------------------------------------------------------- 1 | /* 2 | * CSS for jsPsych experiments. 3 | * 4 | * This stylesheet provides minimal styling to make jsPsych 5 | * experiments look polished without any additional styles. 6 | */ 7 | 8 | /* Container holding jsPsych content */ 9 | 10 | .jspsych-display-element { 11 | display: flex; 12 | flex-direction: column; 13 | overflow-y: auto; 14 | background-color: rgb(150, 150, 150); 15 | } 16 | 17 | .jspsych-display-element:focus { 18 | outline: none; 19 | } 20 | 21 | .jspsych-content-wrapper { 22 | display: flex; 23 | margin: auto; 24 | flex: 1 1 100%; 25 | width: 100%; 26 | } 27 | 28 | .jspsych-content { 29 | max-width: 95%; /* this is mainly an IE 10-11 fix */ 30 | text-align: center; 31 | margin: auto; /* this is for overflowing content */ 32 | } 33 | 34 | .jspsych-top { 35 | align-items: flex-start; 36 | } 37 | 38 | .jspsych-middle { 39 | align-items: center; 40 | } 41 | 42 | /* fonts and type */ 43 | 44 | @import url(https://fonts.googleapis.com/css?family=Open+Sans:400italic,700italic,400,700); 45 | 46 | .jspsych-display-element { 47 | font-family: 'Open Sans', 'Arial', sans-serif; 48 | font-size: 18px; 49 | line-height: 1.6em; 50 | } 51 | 52 | /* Form elements like input fields and buttons */ 53 | 54 | .jspsych-display-element input[type="text"] { 55 | font-family: 'Open Sans', 'Arial', sans-serif; 56 | font-size: 14px; 57 | } 58 | 59 | /* borrowing Bootstrap style for btn elements, but combining styles a bit */ 60 | .jspsych-btn { 61 | display: inline-block; 62 | padding: 6px 12px; 63 | margin: 0px; 64 | font-size: 14px; 65 | font-weight: 400; 66 | font-family: 'Open Sans', 'Arial', sans-serif; 67 | cursor: pointer; 68 | line-height: 1.4; 69 | text-align: center; 70 | white-space: nowrap; 71 | vertical-align: middle; 72 | background-image: none; 73 | border: 1px solid transparent; 74 | border-radius: 4px; 75 | color: #333; 76 | background-color: #fff; 77 | border-color: #ccc; 78 | } 79 | 80 | .jspsych-btn:hover { 81 | background-color: #ddd; 82 | border-color: #aaa; 83 | } 84 | 85 | .jspsych-btn:disabled { 86 | background-color: #eee; 87 | color: #aaa; 88 | border-color: #ccc; 89 | cursor: not-allowed; 90 | } 91 | 92 | /* jsPsych progress bar */ 93 | 94 | #jspsych-progressbar-container { 95 | color: #555; 96 | border-bottom: 1px solid #dedede; 97 | background-color: #f9f9f9; 98 | margin-bottom: 1em; 99 | text-align: center; 100 | padding: 8px 0px; 101 | width: 100%; 102 | line-height: 1em; 103 | } 104 | #jspsych-progressbar-container span { 105 | font-size: 14px; 106 | padding-right: 14px; 107 | } 108 | #jspsych-progressbar-outer { 109 | background-color: #eee; 110 | width: 50%; 111 | margin: auto; 112 | height: 14px; 113 | display: inline-block; 114 | vertical-align: middle; 115 | box-shadow: inset 0 1px 2px rgba(0,0,0,0.1); 116 | } 117 | #jspsych-progressbar-inner { 118 | background-color: #aaa; 119 | width: 0%; 120 | height: 100%; 121 | } 122 | 123 | /* Control appearance of jsPsych.data.displayData() */ 124 | #jspsych-data-display { 125 | text-align: left; 126 | } 127 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Working Memory Tests 2 | Working memory experiment tasks designed on JavaScript 3 | 4 | 5 | Four classic working memory (WM) tests are included in this directory. All have been designed on JavaScript using the jsPsych library (https://www.jspsych.org/). These WM tests have previously been used in lab experiments (data from experiments is included in directory). Paper resulting from these experiments can be found here: https://mindmodeling.org/cogsci2019/papers/0141/index.html. 6 | 7 | Since these tasks are browser based, they can be conveniently used for online experiments (e.g., on MTurk). However, given that online experiments have less controlled environments, the reliability of WM measures might be affected. 8 | 9 | 1) **Digit span test.** This is a verbal-numeric WM storage task. Methods from this test resemble those descibed in Woods et al (2011; https://www.ncbi.nlm.nih.gov/pmc/articles/PMC2978794/). Participants are required to memorize a string of digits and recall them. A demonstration of the task can be viewed here: https://abcwest.cogs.indiana.edu/mkl/WM_battery/digit_span_task.html. 10 | 11 | 2) **Operation span test.** This is a verbal-numeric WM processing task. Methods from this task resemble those described in Oswald et al (2014; https://link.springer.com/article/10.3758/s13428-014-0543-2). Participants are required to memorize a string of letters while simultaneously performing simple mathematical calculations. A demonstration of the task can be viewed here: https://abcwest.cogs.indiana.edu/mkl/WM_battery/operation_span_task.html. 12 | 13 | 3) **Visual array test.** This is a visuo-spatial WM storage task. Methods from this test resemble those described in Cowan et al (2006; https://www.ncbi.nlm.nih.gov/pubmed/17489300). Participants have to quickly memorize colors of squares and detect changes. A demonstration of the task can be viewed here: https://abcwest.cogs.indiana.edu/mkl/WM_battery/visual_array_task.html. 14 | 15 | 4) **Symmetry span test.** This is a visuo-spatial WM processing task. Methods from this task resemble those described in Oswald et al (2014; https://link.springer.com/article/10.3758/s13428-014-0543-2). Participants are required to memorize locations of colored squares on a grid while simultaneously performing simple symmetry judgement decisions. A demonstration of the task can be viewed here: https://abcwest.cogs.indiana.edu/mkl/WM_battery/symmetry_span_task.html. 16 | 17 | 18 | Each of these tasks can be customized to some extent (number of trials, set size in trials, trial duration etc). Easily customizable variables have been listed at the top of each code. Please download all folders in this directory for use of any of the tasks (i.e., 'jspsych-6.0.4' and 'img'). Results from the task can either be stored locally or on a server (through use of an included .php script). Please cite the paper (https://mindmodeling.org/cogsci2019/papers/0141/index.html) if using the tests or the data. If more information is needed, get in touch :) 19 | 20 | APA Citation: [Luthra, M., & Todd, P. M. (2019). Role of working memory on strategy use in the probability learning task. In A. Goel, C. Seifert, & C. Freksa (Eds.), Proceedings of the 41st Annual Conference of the Cognitive Science Society (pp. 721–728). Montreal, QB: Cognitive Science Society.] 21 | -------------------------------------------------------------------------------- /jspsych-6.0.4/plugins/jspsych-spatial-span.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Example plugin template 3 | */ 4 | 5 | jsPsych.plugins["spatial-span"] = (function() { 6 | 7 | var plugin = {}; 8 | 9 | jsPsych.pluginAPI.registerPreload('visual-search-circle', 'target', 'image'); 10 | jsPsych.pluginAPI.registerPreload('visual-search-circle', 'foil', 'image'); 11 | jsPsych.pluginAPI.registerPreload('visual-search-circle', 'fixation_image', 'image'); 12 | 13 | 14 | plugin.info = { 15 | name: 'spatial-span', 16 | description: '', 17 | parameters: { 18 | grid_size: { 19 | type: jsPsych.plugins.parameterType.INT, // INT, IMAGE, KEYCODE, STRING, FUNCTION, FLOAT 20 | default_value: 4, 21 | description: 'size of grid for stimuli.' 22 | }, 23 | trial_duration: { 24 | type: jsPsych.plugins.parameterType.INT, 25 | pretty_name: 'Trial duration', 26 | default: null, 27 | description: 'How long to show the trial.' 28 | }, 29 | size_cells: { 30 | type: jsPsych.plugins.parameterType.INT, 31 | pretty_name: 'Trial duration', 32 | default: 70, 33 | description: 'How long to show the trial.' 34 | }, 35 | selected_box: { 36 | type: jsPsych.plugins.parameterType.INT, 37 | default: undefined, 38 | description: "which box should be selected for this trial" 39 | }, 40 | display_red_box: { 41 | type: jsPsych.plugins.parameterType.BOOL, 42 | default: true, 43 | description: "should a rd box be marked" 44 | } 45 | } 46 | } 47 | 48 | 49 | plugin.trial = function(display_element, trial) { 50 | 51 | // making matrix: 52 | var grid = trial.grid_size; 53 | 54 | var matrix = []; 55 | for (var i=0; i'; 68 | var paper = display_element.querySelector("#jspsych-html-button-response-btngroup"); 69 | 70 | for (var i=0; i
'; 72 | } 73 | 74 | if (trial.display_red_box){ 75 | paper.innerHTML += '
'; 76 | } 77 | 78 | var start_time = Date.now(); 79 | 80 | if (trial.trial_duration !== null) { 81 | jsPsych.pluginAPI.setTimeout(function() { 82 | clear_display(); 83 | end_trial(); 84 | }, trial.trial_duration); 85 | } 86 | 87 | 88 | function clear_display(){ 89 | display_element.innerHTML = ''; 90 | } 91 | 92 | 93 | function end_trial() { 94 | 95 | // kill any remaining setTimeout handlers 96 | jsPsych.pluginAPI.clearAllTimeouts(); 97 | 98 | // gather the data to store for the trial 99 | var trial_data = { 100 | selected_square: red_box 101 | }; 102 | 103 | // move on to the next trial 104 | jsPsych.finishTrial(trial_data); 105 | } 106 | }; 107 | 108 | return plugin; 109 | })(); 110 | -------------------------------------------------------------------------------- /jspsych-6.0.4/plugins/jspsych-fullscreen.js: -------------------------------------------------------------------------------- 1 | /* jspsych-fullscreen.js 2 | * Josh de Leeuw 3 | * 4 | * toggle fullscreen mode in the browser 5 | * 6 | */ 7 | 8 | jsPsych.plugins.fullscreen = (function() { 9 | 10 | var plugin = {}; 11 | 12 | plugin.info = { 13 | name: 'fullscreen', 14 | description: '', 15 | parameters: { 16 | fullscreen_mode: { 17 | type: jsPsych.plugins.parameterType.BOOL, 18 | pretty_name: 'Fullscreen mode', 19 | default: true, 20 | array: false, 21 | description: 'If true, experiment will enter fullscreen mode. If false, the browser will exit fullscreen mode.' 22 | }, 23 | message: { 24 | type: jsPsych.plugins.parameterType.STRING, 25 | pretty_name: 'Message', 26 | default: '

The experiment will switch to full screen mode when you press the button below

', 27 | array: false, 28 | description: 'HTML content to display above the button to enter fullscreen mode.' 29 | }, 30 | button_label: { 31 | type: jsPsych.plugins.parameterType.STRING, 32 | pretty_name: 'Button label', 33 | default: 'Continue', 34 | array: false, 35 | description: 'The text that appears on the button to enter fullscreen.' 36 | }, 37 | delay_after: { 38 | type: jsPsych.plugins.parameterType.INT, 39 | pretty_name: 'Delay after', 40 | default: 1000, 41 | array: false, 42 | description: 'The length of time to delay after entering fullscreen mode before ending the trial.' 43 | }, 44 | } 45 | } 46 | 47 | plugin.trial = function(display_element, trial) { 48 | 49 | // check if keys are allowed in fullscreen mode 50 | var keyboardNotAllowed = typeof Element !== 'undefined' && 'ALLOW_KEYBOARD_INPUT' in Element; 51 | if (keyboardNotAllowed) { 52 | // This is Safari, and keyboard events will be disabled. Don't allow fullscreen here. 53 | // do something else? 54 | endTrial(); 55 | } else { 56 | if(trial.fullscreen_mode){ 57 | display_element.innerHTML = trial.message + ''; 58 | var listener = display_element.querySelector('#jspsych-fullscreen-btn').addEventListener('click', function() { 59 | var element = document.documentElement; 60 | if (element.requestFullscreen) { 61 | element.requestFullscreen(); 62 | } else if (element.mozRequestFullScreen) { 63 | element.mozRequestFullScreen(); 64 | } else if (element.webkitRequestFullscreen) { 65 | element.webkitRequestFullscreen(); 66 | } else if (element.msRequestFullscreen) { 67 | element.msRequestFullscreen(); 68 | } 69 | endTrial(); 70 | }); 71 | } else { 72 | if (document.exitFullscreen) { 73 | document.exitFullscreen(); 74 | } else if (document.msExitFullscreen) { 75 | document.msExitFullscreen(); 76 | } else if (document.mozCancelFullScreen) { 77 | document.mozCancelFullScreen(); 78 | } else if (document.webkitExitFullscreen) { 79 | document.webkitExitFullscreen(); 80 | } 81 | endTrial(); 82 | } 83 | } 84 | 85 | function endTrial() { 86 | 87 | display_element.innerHTML = ''; 88 | 89 | jsPsych.pluginAPI.setTimeout(function(){ 90 | 91 | var trial_data = { 92 | success: !keyboardNotAllowed 93 | }; 94 | 95 | jsPsych.finishTrial(trial_data); 96 | 97 | }, trial.delay_after); 98 | 99 | } 100 | 101 | }; 102 | 103 | return plugin; 104 | })(); 105 | -------------------------------------------------------------------------------- /jspsych-6.0.4/plugins/jspsych-html-keyboard-response.js: -------------------------------------------------------------------------------- 1 | /** 2 | * jspsych-html-keyboard-response 3 | * Josh de Leeuw 4 | * 5 | * plugin for displaying a stimulus and getting a keyboard response 6 | * 7 | * documentation: docs.jspsych.org 8 | * 9 | **/ 10 | 11 | 12 | jsPsych.plugins["html-keyboard-response"] = (function() { 13 | 14 | var plugin = {}; 15 | 16 | plugin.info = { 17 | name: 'html-keyboard-response', 18 | description: '', 19 | parameters: { 20 | stimulus: { 21 | type: jsPsych.plugins.parameterType.HTML_STRING, 22 | pretty_name: 'Stimulus', 23 | default: undefined, 24 | description: 'The HTML string to be displayed' 25 | }, 26 | choices: { 27 | type: jsPsych.plugins.parameterType.KEYCODE, 28 | array: true, 29 | pretty_name: 'Choices', 30 | default: jsPsych.ALL_KEYS, 31 | description: 'The keys the subject is allowed to press to respond to the stimulus.' 32 | }, 33 | prompt: { 34 | type: jsPsych.plugins.parameterType.STRING, 35 | pretty_name: 'Prompt', 36 | default: null, 37 | description: 'Any content here will be displayed below the stimulus.' 38 | }, 39 | stimulus_duration: { 40 | type: jsPsych.plugins.parameterType.INT, 41 | pretty_name: 'Stimulus duration', 42 | default: null, 43 | description: 'How long to hide the stimulus.' 44 | }, 45 | trial_duration: { 46 | type: jsPsych.plugins.parameterType.INT, 47 | pretty_name: 'Trial duration', 48 | default: null, 49 | description: 'How long to show trial before it ends.' 50 | }, 51 | response_ends_trial: { 52 | type: jsPsych.plugins.parameterType.BOOL, 53 | pretty_name: 'Response ends trial', 54 | default: true, 55 | description: 'If true, trial will end when subject makes a response.' 56 | }, 57 | 58 | } 59 | } 60 | 61 | plugin.trial = function(display_element, trial) { 62 | 63 | var new_html = '
'+trial.stimulus+'
'; 64 | 65 | // add prompt 66 | if(trial.prompt !== null){ 67 | new_html += trial.prompt; 68 | } 69 | 70 | // draw 71 | display_element.innerHTML = new_html; 72 | 73 | // store response 74 | var response = { 75 | rt: null, 76 | key: null 77 | }; 78 | 79 | // function to end trial when it is time 80 | var end_trial = function() { 81 | 82 | // kill any remaining setTimeout handlers 83 | jsPsych.pluginAPI.clearAllTimeouts(); 84 | 85 | // kill keyboard listeners 86 | if (typeof keyboardListener !== 'undefined') { 87 | jsPsych.pluginAPI.cancelKeyboardResponse(keyboardListener); 88 | } 89 | 90 | // gather the data to store for the trial 91 | var trial_data = { 92 | "rt": response.rt, 93 | "stimulus": trial.stimulus, 94 | "key_press": response.key 95 | }; 96 | 97 | // clear the display 98 | display_element.innerHTML = ''; 99 | 100 | // move on to the next trial 101 | jsPsych.finishTrial(trial_data); 102 | }; 103 | 104 | // function to handle responses by the subject 105 | var after_response = function(info) { 106 | 107 | // after a valid response, the stimulus will have the CSS class 'responded' 108 | // which can be used to provide visual feedback that a response was recorded 109 | display_element.querySelector('#jspsych-html-keyboard-response-stimulus').className += ' responded'; 110 | 111 | // only record the first response 112 | if (response.key == null) { 113 | response = info; 114 | } 115 | 116 | if (trial.response_ends_trial) { 117 | end_trial(); 118 | } 119 | }; 120 | 121 | // start the response listener 122 | if (trial.choices != jsPsych.NO_KEYS) { 123 | var keyboardListener = jsPsych.pluginAPI.getKeyboardResponse({ 124 | callback_function: after_response, 125 | valid_responses: trial.choices, 126 | rt_method: 'date', 127 | persist: false, 128 | allow_held_key: false 129 | }); 130 | } 131 | 132 | // hide stimulus if stimulus_duration is set 133 | if (trial.stimulus_duration !== null) { 134 | jsPsych.pluginAPI.setTimeout(function() { 135 | display_element.querySelector('#jspsych-html-keyboard-response-stimulus').style.visibility = 'hidden'; 136 | }, trial.stimulus_duration); 137 | } 138 | 139 | // end trial if trial_duration is set 140 | if (trial.trial_duration !== null) { 141 | jsPsych.pluginAPI.setTimeout(function() { 142 | end_trial(); 143 | }, trial.trial_duration); 144 | } 145 | 146 | }; 147 | 148 | return plugin; 149 | })(); 150 | -------------------------------------------------------------------------------- /jspsych-6.0.4/css/jspsych_digitspan.css: -------------------------------------------------------------------------------- 1 | /* 2 | * CSS for jsPsych experiments. 3 | * 4 | * This stylesheet provides minimal styling to make jsPsych 5 | * experiments look polished without any additional styles. 6 | */ 7 | 8 | /* Container holding jsPsych content */ 9 | 10 | .jspsych-display-element { 11 | display: flex; 12 | flex-direction: column; 13 | overflow-y: auto; 14 | 15 | } 16 | 17 | .jspsych-display-element:focus { 18 | outline: none; 19 | } 20 | 21 | .jspsych-content-wrapper { 22 | display: flex; 23 | margin: auto; 24 | flex: 1 1 100%; 25 | width: 100%; 26 | } 27 | 28 | .jspsych-content { 29 | max-width: 95%; /* this is mainly an IE 10-11 fix */ 30 | text-align: center; 31 | margin: auto; /* this is for overflowing content */ 32 | } 33 | 34 | .jspsych-top { 35 | align-items: flex-start; 36 | } 37 | 38 | .jspsych-middle { 39 | align-items: center; 40 | } 41 | 42 | /* fonts and type */ 43 | 44 | @import url(https://fonts.googleapis.com/css?family=Open+Sans:400italic,700italic,400,700); 45 | 46 | .jspsych-display-element { 47 | font-family: 'Open Sans', 'Arial', sans-serif; 48 | font-size: 18px; 49 | line-height: 1.6em; 50 | } 51 | 52 | .jspsych-digit-span-recall{ 53 | display: inline-block; 54 | width:64px; 55 | height:64px; 56 | border:3px solid #000000; 57 | font-size: 35px; 58 | font-weight: 400; 59 | font-family: 'Open Sans', 'Arial', sans-serif; 60 | cursor: pointer; 61 | text-align: center; 62 | vertical-align: middle; 63 | line-height: 74px; 64 | } 65 | 66 | .jspsych-digit-span-recall:hover{ 67 | background-color: rgba(220,0,0,0.3); 68 | display: inline-block; 69 | width:64px; 70 | height:64px; 71 | border:3px solid #000000; 72 | font-weight: 400; 73 | font-family: 'Open Sans', 'Arial', sans-serif; 74 | cursor: pointer; 75 | text-align: center; 76 | vertical-align: middle; 77 | line-height: 74px; 78 | } 79 | 80 | 81 | /* Form elements like input fields and buttons */ 82 | 83 | .jspsych-display-element input[type="text"] { 84 | font-family: 'Open Sans', 'Arial', sans-serif; 85 | font-size: 14px; 86 | } 87 | 88 | /* borrowing Bootstrap style for btn elements, but combining styles a bit */ 89 | .jspsych-btn-numpad { 90 | width: 85px; 91 | display: inline-block; 92 | padding: 6px 12px; 93 | margin: 0px; 94 | font-size: 18px; 95 | font-weight: 400; 96 | font-family: 'Open Sans', 'Arial', sans-serif; 97 | cursor: pointer; 98 | line-height: 1.4; 99 | text-align: center; 100 | white-space: nowrap; 101 | vertical-align: middle; 102 | background-image: none; 103 | border: 1px solid transparent; 104 | border-radius: 4px; 105 | color: #333; 106 | background-color: #fff; 107 | border-color: #ccc; 108 | } 109 | 110 | .jspsych-btn { 111 | display: inline-block; 112 | padding: 6px 12px; 113 | margin: 0px; 114 | font-size: 14px; 115 | font-weight: 400; 116 | font-family: 'Open Sans', 'Arial', sans-serif; 117 | cursor: pointer; 118 | line-height: 1.4; 119 | text-align: center; 120 | white-space: nowrap; 121 | vertical-align: middle; 122 | background-image: none; 123 | border: 1px solid transparent; 124 | border-radius: 4px; 125 | color: #333; 126 | background-color: #fff; 127 | border-color: #ccc; 128 | } 129 | 130 | .jspsych-btn:hover { 131 | background-color: #ddd; 132 | border-color: #aaa; 133 | } 134 | 135 | .jspsych-btn:disabled { 136 | background-color: #eee; 137 | color: #aaa; 138 | border-color: #ccc; 139 | cursor: not-allowed; 140 | } 141 | 142 | .jspsych-btn-numpad:hover { 143 | background-color: #ddd; 144 | border-color: #aaa; 145 | } 146 | 147 | .jspsych-btn-numpad:disabled { 148 | background-color: #eee; 149 | color: #aaa; 150 | border-color: #ccc; 151 | cursor: not-allowed; 152 | } 153 | 154 | .recall-space { 155 | width:400px; 156 | height:64px; 157 | border:0px solid #000000; 158 | font-size: 35px; 159 | font-weight: 400; 160 | font-family: 'Open Sans', 'Arial', sans-serif; 161 | text-align: center; 162 | vertical-align: middle; 163 | line-height: 64px; 164 | } 165 | /* jsPsych progress bar */ 166 | 167 | #jspsych-progressbar-container { 168 | color: #555; 169 | border-bottom: 1px solid #dedede; 170 | background-color: #f9f9f9; 171 | margin-bottom: 1em; 172 | text-align: center; 173 | padding: 8px 0px; 174 | width: 100%; 175 | line-height: 1em; 176 | } 177 | #jspsych-progressbar-container span { 178 | font-size: 14px; 179 | padding-right: 14px; 180 | } 181 | #jspsych-progressbar-outer { 182 | background-color: #eee; 183 | width: 50%; 184 | margin: auto; 185 | height: 14px; 186 | display: inline-block; 187 | vertical-align: middle; 188 | box-shadow: inset 0 1px 2px rgba(0,0,0,0.1); 189 | } 190 | #jspsych-progressbar-inner { 191 | background-color: #aaa; 192 | width: 0%; 193 | height: 100%; 194 | } 195 | 196 | /* Control appearance of jsPsych.data.displayData() */ 197 | #jspsych-data-display { 198 | text-align: left; 199 | } 200 | -------------------------------------------------------------------------------- /jspsych-6.0.4/css/jspsych_operationspan.css: -------------------------------------------------------------------------------- 1 | /* 2 | * CSS for jsPsych experiments. 3 | * 4 | * This stylesheet provides minimal styling to make jsPsych 5 | * experiments look polished without any additional styles. 6 | */ 7 | 8 | /* Container holding jsPsych content */ 9 | 10 | .jspsych-display-element { 11 | display: flex; 12 | flex-direction: column; 13 | overflow-y: auto; 14 | 15 | } 16 | 17 | .jspsych-display-element:focus { 18 | outline: none; 19 | } 20 | 21 | .jspsych-content-wrapper { 22 | display: flex; 23 | margin: auto; 24 | flex: 1 1 100%; 25 | width: 100%; 26 | } 27 | 28 | .jspsych-content { 29 | max-width: 95%; /* this is mainly an IE 10-11 fix */ 30 | text-align: center; 31 | margin: auto; /* this is for overflowing content */ 32 | } 33 | 34 | .jspsych-top { 35 | align-items: flex-start; 36 | } 37 | 38 | .jspsych-middle { 39 | align-items: center; 40 | } 41 | 42 | /* fonts and type */ 43 | 44 | @import url(https://fonts.googleapis.com/css?family=Open+Sans:400italic,700italic,400,700); 45 | 46 | .jspsych-display-element { 47 | font-family: 'Open Sans', 'Arial', sans-serif; 48 | font-size: 18px; 49 | line-height: 1.6em; 50 | } 51 | 52 | .jspsych-operation-span-recall{ 53 | display: inline-block; 54 | width:64px; 55 | height:64px; 56 | border:3px solid #000000; 57 | font-size: 32px; 58 | font-weight: 400; 59 | font-family: 'Open Sans', 'Arial', sans-serif; 60 | cursor: pointer; 61 | text-align: center; 62 | vertical-align: middle; 63 | line-height: 64px; 64 | } 65 | 66 | .jspsych-operation-span-recall:hover{ 67 | background-color: rgba(220,0,0,0.3); 68 | display: inline-block; 69 | width:64px; 70 | height:64px; 71 | border:3px solid #000000; 72 | font-weight: 400; 73 | font-family: 'Open Sans', 'Arial', sans-serif; 74 | cursor: pointer; 75 | text-align: center; 76 | vertical-align: middle; 77 | line-height: 64px; 78 | } 79 | 80 | 81 | /* Form elements like input fields and buttons */ 82 | 83 | .jspsych-display-element input[type="text"] { 84 | font-family: 'Open Sans', 'Arial', sans-serif; 85 | font-size: 14px; 86 | } 87 | 88 | /* borrowing Bootstrap style for btn elements, but combining styles a bit */ 89 | .jspsych-btn-numpad { 90 | width: 85px; 91 | display: inline-block; 92 | padding: 6px 12px; 93 | margin: 0px; 94 | font-size: 18px; 95 | font-weight: 400; 96 | font-family: 'Open Sans', 'Arial', sans-serif; 97 | cursor: pointer; 98 | line-height: 1.4; 99 | text-align: center; 100 | white-space: nowrap; 101 | vertical-align: middle; 102 | background-image: none; 103 | border: 1px solid transparent; 104 | border-radius: 4px; 105 | color: #333; 106 | background-color: #fff; 107 | border-color: #ccc; 108 | } 109 | 110 | .jspsych-btn { 111 | display: inline-block; 112 | padding: 6px 12px; 113 | margin: 0px; 114 | font-size: 14px; 115 | font-weight: 400; 116 | font-family: 'Open Sans', 'Arial', sans-serif; 117 | cursor: pointer; 118 | line-height: 1.4; 119 | text-align: center; 120 | white-space: nowrap; 121 | vertical-align: middle; 122 | background-image: none; 123 | border: 1px solid transparent; 124 | border-radius: 4px; 125 | color: #333; 126 | background-color: #fff; 127 | border-color: #ccc; 128 | } 129 | 130 | .jspsych-btn:hover { 131 | background-color: #ddd; 132 | border-color: #aaa; 133 | } 134 | 135 | .jspsych-btn:disabled { 136 | background-color: #eee; 137 | color: #aaa; 138 | border-color: #ccc; 139 | cursor: not-allowed; 140 | } 141 | 142 | .jspsych-btn-numpad:hover { 143 | background-color: #ddd; 144 | border-color: #aaa; 145 | } 146 | 147 | .jspsych-btn-numpad:disabled { 148 | background-color: #eee; 149 | color: #aaa; 150 | border-color: #ccc; 151 | cursor: not-allowed; 152 | } 153 | 154 | .recall-space { 155 | width:400px; 156 | height:64px; 157 | border:0px solid #000000; 158 | font-size: 35px; 159 | font-weight: 400; 160 | font-family: 'Open Sans', 'Arial', sans-serif; 161 | text-align: center; 162 | vertical-align: middle; 163 | line-height: 64px; 164 | } 165 | /* jsPsych progress bar */ 166 | 167 | #jspsych-progressbar-container { 168 | color: #555; 169 | border-bottom: 1px solid #dedede; 170 | background-color: #f9f9f9; 171 | margin-bottom: 1em; 172 | text-align: center; 173 | padding: 8px 0px; 174 | width: 100%; 175 | line-height: 1em; 176 | } 177 | #jspsych-progressbar-container span { 178 | font-size: 14px; 179 | padding-right: 14px; 180 | } 181 | #jspsych-progressbar-outer { 182 | background-color: #eee; 183 | width: 50%; 184 | margin: auto; 185 | height: 14px; 186 | display: inline-block; 187 | vertical-align: middle; 188 | box-shadow: inset 0 1px 2px rgba(0,0,0,0.1); 189 | } 190 | #jspsych-progressbar-inner { 191 | background-color: #aaa; 192 | width: 0%; 193 | height: 100%; 194 | } 195 | 196 | /* Control appearance of jsPsych.data.displayData() */ 197 | #jspsych-data-display { 198 | text-align: left; 199 | } 200 | -------------------------------------------------------------------------------- /jspsych-6.0.4/plugins/jspsych-survey-text.js: -------------------------------------------------------------------------------- 1 | /** 2 | * jspsych-survey-text 3 | * a jspsych plugin for free response survey questions 4 | * 5 | * Josh de Leeuw 6 | * 7 | * documentation: docs.jspsych.org 8 | * 9 | */ 10 | 11 | 12 | jsPsych.plugins['survey-text'] = (function() { 13 | 14 | var plugin = {}; 15 | 16 | plugin.info = { 17 | name: 'survey-text', 18 | description: '', 19 | parameters: { 20 | questions: { 21 | type: jsPsych.plugins.parameterType.COMPLEX, 22 | array: true, 23 | pretty_name: 'Questions', 24 | default: undefined, 25 | nested: { 26 | prompt: { 27 | type: jsPsych.plugins.parameterType.STRING, 28 | pretty_name: 'Prompt', 29 | default: undefined, 30 | description: 'Prompt for the subject to response' 31 | }, 32 | value: { 33 | type: jsPsych.plugins.parameterType.STRING, 34 | pretty_name: 'Value', 35 | default: "", 36 | description: 'The string will be used to populate the response field with editable answer.' 37 | }, 38 | rows: { 39 | type: jsPsych.plugins.parameterType.INT, 40 | pretty_name: 'Rows', 41 | default: 1, 42 | description: 'The number of rows for the response text box.' 43 | }, 44 | columns: { 45 | type: jsPsych.plugins.parameterType.INT, 46 | pretty_name: 'Columns', 47 | default: 40, 48 | description: 'The number of columns for the response text box.' 49 | } 50 | } 51 | }, 52 | preamble: { 53 | type: jsPsych.plugins.parameterType.STRING, 54 | pretty_name: 'Preamble', 55 | default: null, 56 | description: 'HTML formatted string to display at the top of the page above all the questions.' 57 | }, 58 | button_label: { 59 | type: jsPsych.plugins.parameterType.STRING, 60 | pretty_name: 'Button label', 61 | default: 'Continue', 62 | description: 'The text that appears on the button to finish the trial.' 63 | } 64 | } 65 | } 66 | 67 | plugin.trial = function(display_element, trial) { 68 | 69 | for (var i = 0; i < trial.questions.length; i++) { 70 | if (typeof trial.questions[i].rows == 'undefined') { 71 | trial.questions[i].rows = 1; 72 | } 73 | } 74 | for (var i = 0; i < trial.questions.length; i++) { 75 | if (typeof trial.questions[i].columns == 'undefined') { 76 | trial.questions[i].columns = 40; 77 | } 78 | } 79 | for (var i = 0; i < trial.questions.length; i++) { 80 | if (typeof trial.questions[i].value == 'undefined') { 81 | trial.questions[i].value = ""; 82 | } 83 | } 84 | 85 | var html = ''; 86 | // show preamble text 87 | if(trial.preamble !== null){ 88 | html += '
'+trial.preamble+'
'; 89 | } 90 | // add questions 91 | for (var i = 0; i < trial.questions.length; i++) { 92 | html += '
'; 93 | html += '

' + trial.questions[i].prompt + '

'; 94 | var autofocus = i == 0 ? "autofocus" : ""; 95 | if(trial.questions[i].rows == 1){ 96 | html += ''; 97 | } else { 98 | html += ''; 99 | } 100 | html += '
'; 101 | } 102 | 103 | // add submit button 104 | html += ''; 105 | 106 | display_element.innerHTML = html; 107 | 108 | display_element.querySelector('#jspsych-survey-text-next').addEventListener('click', function() { 109 | // measure response time 110 | var endTime = (new Date()).getTime(); 111 | var response_time = endTime - startTime; 112 | 113 | // create object to hold responses 114 | var question_data = {}; 115 | var matches = display_element.querySelectorAll('div.jspsych-survey-text-question'); 116 | for(var index=0; index
'; 104 | var paper = display_element.querySelector("#jspsych-html-button-response-btngroup"); 105 | 106 | paper.innerHTML += '
'+ recalledGrid+'
'; 107 | 108 | 109 | var buttons = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "0"]; 110 | 111 | for (var i = 0; i < matrix.length; i++) { 112 | var str = buttons[i] 113 | paper.innerHTML += '
'+str+'
'; 114 | } 115 | 116 | 117 | display_element.innerHTML += '
Backspace
'; 118 | 119 | display_element.innerHTML += '
Continue
'; 120 | 121 | 122 | var start_time = Date.now(); 123 | 124 | display_element.querySelector('#jspsych-html-button-response-button').addEventListener('click', function(e){ 125 | var accuracy = 1 126 | if (correctGrid.length == recalledGrid.length){ 127 | for (var i=0; i'; 120 | var paper = display_element.querySelector("#jspsych-html-button-response-btngroup"); 121 | 122 | paper.innerHTML += '
'+ recalledGrid+'
'; 123 | 124 | 125 | var buttons = ["F","H","J","K","L","N","P","Q","R","S","T","V"] 126 | 127 | for (var i = 0; i < matrix.length; i++) { 128 | var str = buttons[i] 129 | paper.innerHTML += '
'+str+'
'; 130 | } 131 | 132 | 133 | display_element.innerHTML += '
Backspace
'; 134 | 135 | display_element.innerHTML += '
Continue
'; 136 | 137 | 138 | var start_time = Date.now(); 139 | 140 | display_element.querySelector('#jspsych-html-button-response-button').addEventListener('click', function(e){ 141 | var acc=0 142 | for (var i=0; i%choice%', 36 | array: true, 37 | description: 'The html of the button. Can create own style.' 38 | }, 39 | prompt: { 40 | type: jsPsych.plugins.parameterType.STRING, 41 | pretty_name: 'Prompt', 42 | default: null, 43 | description: 'Any content here will be displayed under the button.' 44 | }, 45 | stimulus_duration: { 46 | type: jsPsych.plugins.parameterType.INT, 47 | pretty_name: 'Stimulus duration', 48 | default: null, 49 | description: 'How long to hide the stimulus.' 50 | }, 51 | trial_duration: { 52 | type: jsPsych.plugins.parameterType.INT, 53 | pretty_name: 'Trial duration', 54 | default: null, 55 | description: 'How long to show the trial.' 56 | }, 57 | margin_vertical: { 58 | type: jsPsych.plugins.parameterType.STRING, 59 | pretty_name: 'Margin vertical', 60 | default: '0px', 61 | description: 'The vertical margin of the button.' 62 | }, 63 | margin_horizontal: { 64 | type: jsPsych.plugins.parameterType.STRING, 65 | pretty_name: 'Margin horizontal', 66 | default: '8px', 67 | description: 'The horizontal margin of the button.' 68 | }, 69 | response_ends_trial: { 70 | type: jsPsych.plugins.parameterType.BOOL, 71 | pretty_name: 'Response ends trial', 72 | default: true, 73 | description: 'If true, then trial will end when user responds.' 74 | }, 75 | equation_accuracy: { 76 | type: jsPsych.plugins.parameterType.BOOL, 77 | pretty_name: 'Response ends trial', 78 | default: true, 79 | description: 'If true, then trial will end when user responds.' 80 | } 81 | } 82 | } 83 | 84 | plugin.trial = function(display_element, trial) { 85 | 86 | // display stimulus 87 | var html = '
'+trial.stimulus+'
'; 88 | 89 | //display buttons 90 | var buttons = []; 91 | if (Array.isArray(trial.button_html)) { 92 | if (trial.button_html.length == trial.choices.length) { 93 | buttons = trial.button_html; 94 | } else { 95 | console.error('Error in html-button-response plugin. The length of the button_html array does not equal the length of the choices array'); 96 | } 97 | } else { 98 | for (var i = 0; i < trial.choices.length; i++) { 99 | buttons.push(trial.button_html); 100 | } 101 | } 102 | html += '
'; 103 | for (var i = 0; i < trial.choices.length; i++) { 104 | var str = buttons[i].replace(/%choice%/g, trial.choices[i]); 105 | html += '
'+str+'
'; 106 | } 107 | html += '
'; 108 | 109 | //show prompt if there is one 110 | if (trial.prompt !== null) { 111 | html += trial.prompt; 112 | } 113 | display_element.innerHTML = html; 114 | 115 | // start time 116 | var start_time = Date.now(); 117 | 118 | // add event listeners to buttons 119 | for (var i = 0; i < trial.choices.length; i++) { 120 | display_element.querySelector('#jspsych-html-button-response-button-' + i).addEventListener('click', function(e){ 121 | var choice = e.currentTarget.getAttribute('data-choice'); // don't use dataset for jsdom compatibility 122 | if ((trial.equation_accuracy) && (choice==0)){ 123 | acc = 1 124 | } else if ((!trial.equation_accuracy) && (choice == 1)){ 125 | acc =1 126 | } else{ 127 | acc = 0 128 | } 129 | after_response(acc); 130 | }); 131 | } 132 | 133 | // store response 134 | var response = { 135 | rt: null, 136 | button: null 137 | }; 138 | 139 | // function to handle responses by the subject 140 | function after_response(choice) { 141 | 142 | // measure rt 143 | var end_time = Date.now(); 144 | var rt = end_time - start_time; 145 | response.button = choice; 146 | response.rt = rt; 147 | 148 | // after a valid response, the stimulus will have the CSS class 'responded' 149 | // which can be used to provide visual feedback that a response was recorded 150 | display_element.querySelector('#jspsych-html-button-response-stimulus').className += ' responded'; 151 | 152 | // disable all the buttons after a response 153 | var btns = document.querySelectorAll('.jspsych-html-button-response-button button'); 154 | for(var i=0; i0){ 82 | recalledGrid = recalledGrid.slice(0, (recalledGrid.length-1)) 83 | console.log(recalledGrid) 84 | var div = divArray[divArray.length-1] 85 | var tt = ttArray[ttArray.length-1] 86 | nRecalled -= 1 87 | div.innerHTML = nothing 88 | display_element.querySelector(tt).className ="jspsych-btn-grid" 89 | divArray = divArray.slice(0, (divArray.length-1)) 90 | ttArray = ttArray.slice(0, (ttArray.length-1)) 91 | } 92 | // for (i=0; i'; 121 | var paper = display_element.querySelector("#jspsych-html-button-response-btngroup"); 122 | 123 | for (var i=0; i'+nothing+'';// '; 125 | } 126 | 127 | // display_element.innerHTML += '
Blank
'; 128 | 129 | //display_element.innerHTML += '
' 130 | display_element.innerHTML += '
Backspace
'; 131 | 132 | display_element.innerHTML += '
Continue
'; 133 | 134 | 135 | var start_time = Date.now(); 136 | 137 | 138 | display_element.querySelector('#jspsych-html-button-response-button').addEventListener('click', function(e){ 139 | var acc = 0 140 | for (var i=0; i'; 102 | var paper = display_element.querySelector("#jspsych-visual-array-response-container"); 103 | 104 | // check distractors - array? 105 | if(!Array.isArray(trial.foil)){ 106 | fa = []; 107 | for(var i=0; i"; 132 | 133 | for (var i = 0; i < display_locs.length; i++) { 134 | paper.innerHTML += ""; 135 | } 136 | 137 | var trial_over = false; 138 | 139 | var after_response = function(info) { 140 | 141 | trial_over = true; 142 | 143 | var correct = false; 144 | 145 | if (jsPsych.pluginAPI.compareKeys(info.key,trial.target_different_key) && trial.target_different || 146 | jsPsych.pluginAPI.compareKeys(info.key,trial.target_same_key) && !trial.target_different) { 147 | correct = true; 148 | } 149 | 150 | clear_display(); 151 | 152 | end_trial(info.rt, correct, info.key); 153 | }; 154 | 155 | var valid_keys = []; 156 | valid_keys.push(trial.target_different_key) 157 | valid_keys.push(trial.target_same_key) 158 | 159 | key_listener = jsPsych.pluginAPI.getKeyboardResponse({ 160 | callback_function: after_response, 161 | valid_responses: valid_keys, 162 | rt_method: 'date', 163 | persist: false, 164 | allow_held_key: false 165 | }); 166 | 167 | if (trial.trial_duration !== null) { 168 | jsPsych.pluginAPI.setTimeout(function() { 169 | if (!trial_over) { 170 | jsPsych.pluginAPI.cancelKeyboardResponse(key_listener); 171 | trial_over = true; 172 | var rt = null; 173 | var correct = 0; 174 | var key_press = null; 175 | clear_display(); 176 | end_trial(rt, correct, key_press); 177 | } 178 | }, trial.trial_duration); 179 | } 180 | function clear_display() { 181 | display_element.innerHTML = ''; 182 | } 183 | } 184 | 185 | function end_trial(rt, correct, key_press) { 186 | 187 | // data saving 188 | var trial_data = { 189 | correct: correct, 190 | rt: rt, 191 | key_press: key_press, 192 | // locations: JSON.stringify(display_locs), 193 | target_different: trial.target_different, 194 | // set_size: trial.set_size 195 | }; 196 | 197 | // go to next trial 198 | jsPsych.finishTrial(trial_data); 199 | } 200 | }; 201 | 202 | // helper function for determining stimulus locations 203 | 204 | function cosd(num) { 205 | return Math.cos(num / 180 * Math.PI); 206 | } 207 | 208 | function sind(num) { 209 | return Math.sin(num / 180 * Math.PI); 210 | } 211 | 212 | return plugin; 213 | })(); 214 | -------------------------------------------------------------------------------- /jspsych-6.0.4/README.md: -------------------------------------------------------------------------------- 1 | ![logo](http://www.jspsych.org/img/jspsych-logo.jpg) 2 | 3 | jsPsych is a JavaScript library for creating behavioral experiments that run in a web browser. jsPsych provides a framework for defining experiments using a set of flexible plugins that create different kinds of tasks a subject could complete during an experiment. By assembling these different plugins together it is possible to create many different types of experiments. 4 | 5 | Examples 6 | ---------- 7 | 8 | These examples are intended to illustrate what jsPsych code and experiments look like. There is a larger set of example code in the [examples folder](/examples). 9 | 10 | #### #1: Displaying instructions [(code)](https://github.com/jspsych/jsPsych/tree/master/examples/demos/demo_1.html) 11 |
12 | 13 |
14 | 15 | 16 | ```javascript 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | var trial = { 31 | type: 'instructions', 32 | pages: [ 33 | 'Welcome to the experiment. Click next to begin.', 34 | 35 | '

In this experiment, you will view a ' + 36 | 'series of images and answer questions.

' + 37 | '

Answer with the keys "y" or "n".

', 38 | 39 | '

Here is an example:

' + 40 | '' + 41 | '

Is this person OLD or YOUNG?

' 42 | ], 43 | show_clickable_nav: true 44 | } 45 | 46 | jsPsych.init({ 47 | timeline: [trial], 48 | }); 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | ``` 61 |
62 |
63 |
64 | 65 | 66 | #### #2: Displaying images and recording a response [(code)](https://github.com/jspsych/jsPsych/tree/master/examples/demos/demo_2.html) 67 |
68 | 69 | 70 |
71 | 72 | 73 | ```javascript 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | var trial_1 = { 82 | type: "image-keyboard-response", 83 | stimulus: 'img/happy_face_1.jpg', 84 | choices: ['y', 'n'], 85 | prompt: '

Is this face happy? Y or N.

' 86 | } 87 | 88 | var trial_2 = { 89 | type: 'image-keyboard-response', 90 | stimulus: 'img/sad_face_2.jpg', 91 | choices: ['y', 'n'], 92 | prompt: '

Is this face happy? Y or N.

' 93 | } 94 | 95 | var trial_3 = { 96 | type: 'image-keyboard-response', 97 | stimulus: 'img/happy_face_2.jpg', 98 | choices: ['y', 'n'], 99 | prompt: '

Is this face happy? Y or N.

' 100 | } 101 | 102 | 103 | jsPsych.init({ 104 | timeline: [trial_1, trial_2, trial_3], 105 | default_iti: 250 106 | }); 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | ``` 115 |
116 |
117 |
118 | 119 | #### #3: A flanker task showing a few advanced features of the library [(code)](https://github.com/jspsych/jsPsych/tree/master/examples/demos/demo_3.html) 120 | 121 |
122 | 123 |
124 | 125 | 126 | ```javascript 127 | var test_stimuli = [ 128 | { stimulus: "<<<<<", data: {stim_type: 'congruent'} }, 129 | { stimulus: ">>>>>", data: {stim_type: 'congruent'} }, 130 | { stimulus: "<<><<", data: {stim_type: 'incongruent'} }, 131 | { stimulus: ">><>>", data: {stim_type: 'incongruent'} } 132 | ]; 133 | 134 | var test = { 135 | timeline: [{ 136 | type: 'html-keyboard-response', 137 | choices: [37, 39], 138 | stimulus: jsPsych.timelineVariable('stimulus'), 139 | data: jsPsych.timelineVariable('data'), 140 | post_trial_gap: 1500, 141 | response_ends_trial: true 142 | }], 143 | timeline_variables: test_stimuli, 144 | sample: {type: 'fixed-repetitions', size: 2} 145 | }; 146 | 147 | var debrief = { 148 | type: "html-keyboard-response", 149 | stimulus: function() { 150 | var congruent_rt = Math.round(jsPsych.data.get() 151 | .filter({stim_type: 'congruent'}).select('rt').mean()); 152 | var incongruent_rt = Math.round(jsPsych.data.get() 153 | .filter({stim_type: 'incongruent'}).select('rt').mean()); 154 | return "

Your average response"+ 155 | "time for congruent trials was "+congruent_rt+ 156 | "ms.

"+ 157 | "

Your average response time for"+ 158 | "incongruent trials was "+incongruent_rt+ 159 | "ms.

"; 160 | } 161 | }; 162 | 163 | jsPsych.init({ 164 | timeline: [test, debrief], 165 | }); 166 | ``` 167 |
168 |
169 |
170 | 171 | Documentation 172 | ------------- 173 | 174 | Documentation is available at [docs.jspsych.org](http://docs.jspsych.org). 175 | 176 | Need help? 177 | ---------- 178 | 179 | For questions about using the library, please post to the [jsPsych e-mail list](https://groups.google.com/forum/#!forum/jspsych). This creates a public archive of questions and solutions. 180 | 181 | Contributing 182 | ------------ 183 | 184 | Contributions to the code are welcome. Please use the [Issue tracker system](https://github.com/jodeleeuw/jsPsych/issues) to report bugs or discuss suggestions for new features and improvements. If you would like to contribute code, [submit a Pull request](https://help.github.com/articles/using-pull-requests). 185 | 186 | Citation 187 | -------- 188 | 189 | If you use this library in academic work, please cite the [paper that describes jsPsych](http://link.springer.com/article/10.3758%2Fs13428-014-0458-y): 190 | 191 | 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 192 | 193 | Response times 194 | -------------- 195 | 196 | 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. 197 | 198 | * [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) 199 | * [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) 200 | * [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) 201 | * [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) 202 | 203 | 204 | Credits 205 | ------- 206 | 207 | jsPsych was created by Josh de Leeuw ([@jodeleeuw](https://github.com/jodeleeuw)). 208 | 209 | There have been many [contributors](https://github.com/jodeleeuw/jsPsych/blob/master/contributors.md) to the library. Thank you! 210 | -------------------------------------------------------------------------------- /jspsych-6.0.4/plugins/jspsych-instructions.js: -------------------------------------------------------------------------------- 1 | /* jspsych-instructions.js 2 | * Josh de Leeuw 3 | * 4 | * This plugin displays text (including HTML formatted strings) during the experiment. 5 | * Use it to show instructions, provide performance feedback, etc... 6 | * 7 | * Page numbers can be displayed to help with navigation by setting show_page_number 8 | * to true. 9 | * 10 | * documentation: docs.jspsych.org 11 | * 12 | * 13 | */ 14 | 15 | jsPsych.plugins.instructions = (function() { 16 | 17 | var plugin = {}; 18 | 19 | plugin.info = { 20 | name: 'instructions', 21 | description: '', 22 | parameters: { 23 | pages: { 24 | type: jsPsych.plugins.parameterType.HTML_STRING, 25 | pretty_name: 'Pages', 26 | default: undefined, 27 | array: true, 28 | description: 'Each element of the array is the content for a single page.' 29 | }, 30 | key_forward: { 31 | type: jsPsych.plugins.parameterType.KEYCODE, 32 | pretty_name: 'Key forward', 33 | default: 'rightarrow', 34 | description: 'The key the subject can press in order to advance to the next page.' 35 | }, 36 | key_backward: { 37 | type: jsPsych.plugins.parameterType.KEYCODE, 38 | pretty_name: 'Key backward', 39 | default: 'leftarrow', 40 | description: 'The key that the subject can press to return to the previous page.' 41 | }, 42 | allow_backward: { 43 | type: jsPsych.plugins.parameterType.BOOL, 44 | pretty_name: 'Allow backward', 45 | default: true, 46 | description: 'If true, the subject can return to the previous page of the instructions.' 47 | }, 48 | allow_keys: { 49 | type: jsPsych.plugins.parameterType.BOOL, 50 | pretty_name: 'Allow keys', 51 | default: true, 52 | description: 'If true, the subject can use keyboard keys to navigate the pages.' 53 | }, 54 | show_clickable_nav: { 55 | type: jsPsych.plugins.parameterType.BOOL, 56 | pretty_name: 'Show clickable nav', 57 | default: false, 58 | description: 'If true, then a "Previous" and "Next" button will be displayed beneath the instructions.' 59 | }, 60 | show_page_number: { 61 | type: jsPsych.plugins.parameterType.BOOL, 62 | pretty_name: 'Show page number', 63 | default: false, 64 | description: 'If true, and clickable navigation is enabled, then Page x/y will be shown between the nav buttons.' 65 | }, 66 | button_label_previous: { 67 | type: jsPsych.plugins.parameterType.STRING, 68 | pretty_name: 'Button label previous', 69 | default: 'Previous', 70 | description: 'The text that appears on the button to go backwards.' 71 | }, 72 | button_label_next: { 73 | type: jsPsych.plugins.parameterType.STRING, 74 | pretty_name: 'Button label next', 75 | default: 'Next', 76 | description: 'The text that appears on the button to go forwards.' 77 | } 78 | } 79 | } 80 | 81 | plugin.trial = function(display_element, trial) { 82 | 83 | var current_page = 0; 84 | 85 | var view_history = []; 86 | 87 | var start_time = (new Date()).getTime(); 88 | 89 | var last_page_update_time = start_time; 90 | 91 | function btnListener(evt){ 92 | evt.target.removeEventListener('click', btnListener); 93 | if(this.id === "jspsych-instructions-back"){ 94 | back(); 95 | } 96 | else if(this.id === 'jspsych-instructions-next'){ 97 | next(); 98 | } 99 | } 100 | 101 | function show_current_page() { 102 | let pagenum_display = ""; 103 | if(trial.show_page_number) { 104 | pagenum_display = "Page "+(current_page+1)+"/"+trial.pages.length; 105 | } 106 | display_element.innerHTML = trial.pages[current_page]; 107 | if (trial.show_clickable_nav) { 108 | 109 | var nav_html = "
"; 110 | if (trial.allow_backward) { 111 | let allowed = (current_page > 0 && trial.show_page_number)? '' : "disabled='disabled'"; 112 | nav_html += ""; 113 | } 114 | if (trial.pages.length > 1 && trial.show_page_number) { 115 | nav_html += ""+pagenum_display+""; 117 | } 118 | nav_html += "
"; 121 | 122 | display_element.innerHTML += nav_html; 123 | 124 | if (current_page != 0 && trial.allow_backward) { 125 | display_element.querySelector('#jspsych-instructions-back').addEventListener('click', btnListener); 126 | } 127 | 128 | display_element.querySelector('#jspsych-instructions-next').addEventListener('click', btnListener); 129 | } else if (trial.show_page_number && trial.pages.length > 1) { 130 | // page numbers for non-mouse navigation 131 | display_element.innerHTML += "
"+ 132 | pagenum_display+"
" 133 | } 134 | } 135 | 136 | function next() { 137 | 138 | add_current_page_to_view_history() 139 | 140 | current_page++; 141 | 142 | // if done, finish up... 143 | if (current_page >= trial.pages.length) { 144 | endTrial(); 145 | } else { 146 | show_current_page(); 147 | } 148 | 149 | } 150 | 151 | function back() { 152 | 153 | add_current_page_to_view_history() 154 | 155 | current_page--; 156 | 157 | show_current_page(); 158 | } 159 | 160 | function add_current_page_to_view_history() { 161 | 162 | var current_time = (new Date()).getTime(); 163 | 164 | var page_view_time = current_time - last_page_update_time; 165 | 166 | view_history.push({ 167 | page_index: current_page, 168 | viewing_time: page_view_time 169 | }); 170 | 171 | last_page_update_time = current_time; 172 | } 173 | 174 | function endTrial() { 175 | 176 | if (trial.allow_keys) { 177 | jsPsych.pluginAPI.cancelKeyboardResponse(keyboard_listener); 178 | } 179 | 180 | display_element.innerHTML = ''; 181 | 182 | var trial_data = { 183 | "view_history": JSON.stringify(view_history), 184 | "rt": (new Date()).getTime() - start_time 185 | }; 186 | 187 | jsPsych.finishTrial(trial_data); 188 | } 189 | 190 | var after_response = function(info) { 191 | 192 | // have to reinitialize this instead of letting it persist to prevent accidental skips of pages by holding down keys too long 193 | keyboard_listener = jsPsych.pluginAPI.getKeyboardResponse({ 194 | callback_function: after_response, 195 | valid_responses: [trial.key_forward, trial.key_backward], 196 | rt_method: 'date', 197 | persist: false, 198 | allow_held_key: false 199 | }); 200 | // check if key is forwards or backwards and update page 201 | if (jsPsych.pluginAPI.compareKeys(info.key, trial.key_backward)) { 202 | if (current_page !== 0 && trial.allow_backward) { 203 | back(); 204 | } 205 | } 206 | 207 | if (jsPsych.pluginAPI.compareKeys(info.key, trial.key_forward)) { 208 | next(); 209 | } 210 | 211 | }; 212 | 213 | show_current_page(); 214 | 215 | if (trial.allow_keys) { 216 | var keyboard_listener = jsPsych.pluginAPI.getKeyboardResponse({ 217 | callback_function: after_response, 218 | valid_responses: [trial.key_forward, trial.key_backward], 219 | rt_method: 'date', 220 | persist: false 221 | }); 222 | } 223 | }; 224 | 225 | return plugin; 226 | })(); 227 | -------------------------------------------------------------------------------- /jspsych-6.0.4/plugins/jspsych-visual-array.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Example plugin template 3 | */ 4 | 5 | jsPsych.plugins["visual-array"] = (function() { 6 | 7 | var plugin = {}; 8 | 9 | jsPsych.pluginAPI.registerPreload('visual-array', 'target', 'image'); 10 | jsPsych.pluginAPI.registerPreload('visual-array', 'foil', 'image'); 11 | jsPsych.pluginAPI.registerPreload('visual-array', 'fixation_image', 'image'); 12 | 13 | 14 | plugin.info = { 15 | name: 'visual-array', 16 | description: '', 17 | parameters: { 18 | stimulus: { 19 | type: jsPsych.plugins.parameterType.HTML_STRING, 20 | pretty_name: 'Stimulus', 21 | default: undefined, 22 | description: 'The HTML string to be displayed' 23 | }, 24 | set_size: { 25 | type: jsPsych.plugins.parameterType.INT, // INT, IMAGE, KEYCODE, STRING, FUNCTION, FLOAT 26 | default_value: 4 27 | }, 28 | number_darkened: { 29 | type: jsPsych.plugins.parameterType.INT, 30 | default_value: undefined 31 | }, 32 | proportion: { 33 | type: jsPsych.plugins.parameterType.FLOAT, 34 | default_value: 0.5 35 | }, 36 | choices: { 37 | type: jsPsych.plugins.parameterType.KEYCODE, 38 | pretty_name: 'Choices', 39 | default: ['Symmetric', 'Assymetric'], 40 | array: true, 41 | description: 'The labels for the buttons.' 42 | }, 43 | button_html: { 44 | type: jsPsych.plugins.parameterType.IMAGE, 45 | pretty_name: 'Button html', 46 | default: '', 47 | array: true, 48 | description: 'The html of the button. Can create own style.' 49 | }, 50 | trial_duration: { 51 | type: jsPsych.plugins.parameterType.INT, 52 | pretty_name: 'Trial duration', 53 | default: null, 54 | description: 'How long to show the trial.' 55 | }, 56 | size_screen: { 57 | type: jsPsych.plugins.parameterType.INT, 58 | pretty_name: 'Trial duration', 59 | default: 350, 60 | description: 'Size of the small viewing area.' 61 | }, 62 | size_boxes: { 63 | type: jsPsych.plugins.parameterType.INT, 64 | pretty_name: 'Trial duration', 65 | default: 20, 66 | description: 'Size of stimuli.' 67 | } 68 | } 69 | } 70 | 71 | 72 | plugin.trial = function(display_element, trial) { 73 | 74 | nStimuli = trial.set_size; 75 | 76 | var N = 20; 77 | var bound = 7 78 | 79 | var ar = Array.apply(null, {length: N}).map(Number.call, Number) 80 | 81 | var mat = [] 82 | for(var i = 0; i < 20; i++) { 83 | mat.push(ar) 84 | } 85 | 86 | var stimuliSpots = []; 87 | for (var i=0; i=0){ 94 | index = mat[i].indexOf(id) 95 | mat[i].splice(index, bound*2) 96 | } 97 | else { 98 | index = mat 99 | } 100 | 101 | 102 | } 103 | 104 | 105 | } 106 | 107 | // creating identical of matrix, but with black boxes removed: 108 | for (i=0; i'; 164 | var paper = display_element.querySelector("#jspsych-visual-search-circle-container"); 165 | 166 | 167 | for (i=0; i'; 169 | } 170 | 171 | for (i=0; i'; 173 | } 174 | 175 | var buttons = []; 176 | if (Array.isArray(trial.button_html)) { 177 | if (trial.button_html.length == trial.choices.length) { 178 | buttons = trial.button_html; 179 | } else { 180 | console.error('Error in html-button-response plugin. The length of the button_html array does not equal the length of the choices array'); 181 | } 182 | } else { 183 | for (var i = 0; i < trial.choices.length; i++) { 184 | buttons.push(trial.button_html); 185 | } 186 | } 187 | 188 | var html = '
'; 189 | for (var i = 0; i < trial.choices.length; i++) { 190 | var str = buttons[i].replace(/%choice%/g, trial.choices[i]); 191 | html += '
'+str+'
'; 192 | } 193 | html += '
'; 194 | 195 | display_element.innerHTML+=html 196 | 197 | var start_time = Date.now(); 198 | 199 | // add event listeners to buttons 200 | for (var i = 0; i < trial.choices.length; i++) { 201 | display_element.querySelector('#jspsych-html-button-response-button-' + i).addEventListener('click', function(e){ 202 | var choice = e.currentTarget.getAttribute('data-choice'); // don't use dataset for jsdom compatibility 203 | after_response(choice); 204 | }); 205 | } 206 | 207 | // store response 208 | var response = { 209 | rt: null, 210 | button: null 211 | }; 212 | 213 | function after_response(choice) { 214 | 215 | // measure rt 216 | var end_time = Date.now(); 217 | var rt = end_time - start_time; 218 | var choiceRecord = choice; 219 | response.button = choice; 220 | response.rt = rt; 221 | 222 | // after a valid response, the stimulus will have the CSS class 'responded' 223 | // which can be used to provide visual feedback that a response was recorded 224 | //display_element.querySelector('#jspsych-html-button-response-stimulus').className += ' responded'; 225 | 226 | // disable all the buttons after a response 227 | var btns = document.querySelectorAll('.jspsych-html-button-response-button button'); 228 | for(var i=0; i%choice%', 47 | array: true, 48 | description: 'The html of the button. Can create own style.' 49 | }, 50 | trial_duration: { 51 | type: jsPsych.plugins.parameterType.INT, 52 | pretty_name: 'Trial duration', 53 | default: null, 54 | description: 'How long to show the trial.' 55 | }, 56 | size_cells: { 57 | type: jsPsych.plugins.parameterType.INT, 58 | pretty_name: 'Trial duration', 59 | default: 50, 60 | description: 'How long to show the trial.' 61 | } 62 | } 63 | } 64 | 65 | 66 | 67 | 68 | 69 | plugin.trial = function(display_element, trial) { 70 | 71 | // var html = '
'+trial.stimulus+'
'; 72 | // display_element.innerHTML =html 73 | 74 | // making half of matrix: 75 | var rows = trial.size; 76 | var columns = trial.size/2; 77 | var matrix= []; 78 | for (var i=0; i'; 147 | var paper = display_element.querySelector("#jspsych-visual-search-circle-container"); 148 | 149 | 150 | for (i=0; i'; 152 | } 153 | 154 | for (i=0; i'; 156 | } 157 | 158 | var buttons = []; 159 | if (Array.isArray(trial.button_html)) { 160 | if (trial.button_html.length == trial.choices.length) { 161 | buttons = trial.button_html; 162 | } else { 163 | console.error('Error in html-button-response plugin. The length of the button_html array does not equal the length of the choices array'); 164 | } 165 | } else { 166 | for (var i = 0; i < trial.choices.length; i++) { 167 | buttons.push(trial.button_html); 168 | } 169 | } 170 | 171 | var html = '
'; 172 | for (var i = 0; i < trial.choices.length; i++) { 173 | var str = buttons[i].replace(/%choice%/g, trial.choices[i]); 174 | html += '
'+str+'
'; 175 | } 176 | html += '
'; 177 | 178 | display_element.innerHTML+=html 179 | 180 | var start_time = Date.now(); 181 | 182 | // add event listeners to buttons 183 | for (var i = 0; i < trial.choices.length; i++) { 184 | display_element.querySelector('#jspsych-html-button-response-button-' + i).addEventListener('click', function(e){ 185 | var choice = e.currentTarget.getAttribute('data-choice'); // don't use dataset for jsdom compatibility 186 | after_response(choice); 187 | }); 188 | } 189 | 190 | // store response 191 | var response = { 192 | rt: null, 193 | button: null 194 | }; 195 | 196 | function after_response(choice) { 197 | var accuracy= 0 198 | var correctR = "" + pSymmetric 199 | if (correctR == choice){ 200 | accuracy = 1 201 | } 202 | // console.log(pSymmetric, choice, accuracy) 203 | 204 | // measure rt 205 | var end_time = Date.now(); 206 | var rt = end_time - start_time; 207 | var choiceRecord = choice; 208 | response.correct = accuracy; 209 | response.rt = rt; 210 | 211 | // after a valid response, the stimulus will have the CSS class 'responded' 212 | // which can be used to provide visual feedback that a response was recorded 213 | //display_element.querySelector('#jspsych-html-button-response-stimulus').className += ' responded'; 214 | 215 | // disable all the buttons after a response 216 | var btns = document.querySelectorAll('.jspsych-html-button-response-button button'); 217 | for(var i=0; i 2 | 3 | WM visual array task 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 224 | 225 | -------------------------------------------------------------------------------- /jspsych-6.0.4/plugins/jspsych-visual-array-stimuli.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * jspsych-visual-search-circle 4 | * Josh de Leeuw 5 | * 6 | * display a set of objects, with or without a target, equidistant from fixation 7 | * subject responds to whether or not the target is present 8 | * 9 | * based on code written for psychtoolbox by Ben Motz 10 | * 11 | * documentation: docs.jspsych.org 12 | * 13 | **/ 14 | 15 | jsPsych.plugins["visual-array-stimuli"] = (function() { 16 | 17 | var plugin = {}; 18 | 19 | jsPsych.pluginAPI.registerPreload('visual-array-stimuli', 'target', 'image'); 20 | jsPsych.pluginAPI.registerPreload('visual-array-stimuli', 'foil', 'image'); 21 | jsPsych.pluginAPI.registerPreload('visual-array-stimuli', 'fixation_image', 'image'); 22 | 23 | plugin.info = { 24 | name: 'visual-array-stimuli', 25 | description: '', 26 | parameters: { 27 | set_size: { 28 | type: jsPsych.plugins.parameterType.INT, 29 | pretty_name: 'Set size1', 30 | default: undefined, 31 | description: 'How many items should be displayed?' 32 | }, 33 | target_size: { 34 | type: jsPsych.plugins.parameterType.INT, 35 | pretty_name: 'Target size', 36 | array: true, 37 | default: [60, 60], 38 | description: 'Two element array indicating the height and width of the search array element images.' 39 | }, 40 | fixation_size: { 41 | type: jsPsych.plugins.parameterType.INT, 42 | pretty_name: 'Fixation size', 43 | array: true, 44 | default: [20, 20], 45 | description: 'Two element array indicating the height and width of the fixation image.' 46 | }, 47 | circle_diameter: { 48 | type: jsPsych.plugins.parameterType.INT, 49 | pretty_name: 'Circle diameter1', 50 | default: 260, 51 | description: 'The diameter of the search array circle in pixels.' 52 | }, 53 | trial_duration: { 54 | type: jsPsych.plugins.parameterType.INT, 55 | pretty_name: 'Trial duration', 56 | default: 250, 57 | description: 'The maximum duration to wait for a response.' 58 | } 59 | } 60 | } 61 | 62 | plugin.trial = function(display_element, trial) { 63 | 64 | // circle params 65 | var diam = trial.circle_diameter; // pixels 66 | var radi = diam / 2; 67 | var paper_size = diam + trial.target_size[0]; 68 | 69 | // stimuli width, height 70 | var stimh = trial.target_size[0]; 71 | var stimw = trial.target_size[1]; 72 | var hstimh = stimh / 2; 73 | var hstimw = stimw / 2; 74 | 75 | //fixation location 76 | var centre_loc = [Math.floor(paper_size / 2 - trial.target_size[0] / 2), Math.floor(paper_size / 2 - trial.target_size[1] / 2)]; 77 | 78 | var display = [centre_loc]; 79 | var possible_display_locs1 = 5; 80 | var random_offset1 = Math.floor(Math.random() * 360); 81 | for (var i = 0; i < possible_display_locs1; i++) { 82 | display.push([ 83 | Math.floor(paper_size / 2 + (cosd(random_offset1 + (i * (360 / possible_display_locs1))) * 27) - hstimw), 84 | Math.floor(paper_size / 2 - (sind(random_offset1 + (i * (360 / possible_display_locs1))) * 27) - hstimh) 85 | ]); 86 | } 87 | 88 | var possible_display_locs2 = 10; 89 | var random_offset2 = Math.floor(Math.random() * 360); 90 | for (var i = 0; i < possible_display_locs2; i++) { 91 | display.push([ 92 | Math.floor(paper_size / 2 + (cosd(random_offset2 + (i * (360 / possible_display_locs2))) * 55) - hstimw), 93 | Math.floor(paper_size / 2 - (sind(random_offset2 + (i * (360 / possible_display_locs2))) * 55) - hstimh) 94 | ]); 95 | } 96 | 97 | var possible_display_locs3 = 16; 98 | var random_offset3 = Math.floor(Math.random() * 360); 99 | for (var i = 0; i < possible_display_locs3; i++) { 100 | display.push([ 101 | Math.floor(paper_size / 2 + (cosd(random_offset3 + (i * (360 / possible_display_locs3))) * 83) - hstimw), 102 | Math.floor(paper_size / 2 - (sind(random_offset3 + (i * (360 / possible_display_locs3))) * 83) - hstimh) 103 | ]); 104 | } 105 | 106 | var possible_display_locs4 = 18; 107 | var random_offset4 = Math.floor(Math.random() * 360); 108 | for (var i = 0; i < possible_display_locs4; i++) { 109 | display.push([ 110 | Math.floor(paper_size / 2 + (cosd(random_offset4 + (i * (360 / possible_display_locs4))) * 110) - hstimw), 111 | Math.floor(paper_size / 2 - (sind(random_offset4 + (i * (360 / possible_display_locs4))) * 110) - hstimh) 112 | ]); 113 | } 114 | 115 | var number_stim = trial.set_size; 116 | var weights = Array(display.length).fill(10) 117 | var display_locs = [] 118 | for(var i = 0; i'; 135 | var paper = display_element.querySelector("#jspsych-visual-search-circle-container"); 136 | 137 | // check distractors - array? 138 | if(!Array.isArray(trial.foil)){ 139 | fa = []; 140 | for(var i=0; i"; 154 | } 155 | 156 | // var buttons = []; 157 | // if (Array.isArray(trial.button_html)) { 158 | // if (trial.button_html.length == trial.choices.length) { 159 | // buttons = trial.button_html; 160 | // } else { 161 | // console.error('Error in html-button-response plugin. The length of the button_html array does not equal the length of the choices array'); 162 | // } 163 | // } else { 164 | // for (var i = 0; i < trial.choices.length; i++) { 165 | // buttons.push(trial.button_html); 166 | // } 167 | // } 168 | // paper.innerHTML += '
'; 169 | // for (var i = 0; i < trial.choices.length; i++) { 170 | // var str = buttons[i].replace(/%choice%/g, trial.choices[i]); 171 | // paper.innerHTML += '
'+str+'
'; 172 | // } 173 | // paper.innerHTML += '
'; 174 | 175 | // display_element.innerHTML += '
' 176 | 177 | var start_time = Date.now(); 178 | 179 | // add event listeners to buttons 180 | // for (var i = 0; i < trial.choices.length; i++) { 181 | // display_element.querySelector('#jspsych-html-button-response-button-' + i).addEventListener('click', function(e){ 182 | // var choice = e.currentTarget.getAttribute('data-choice'); // don't use dataset for jsdom compatibility 183 | // after_response(choice); 184 | // }); 185 | // } 186 | 187 | // function to handle responses by the subject 188 | // function after_response(choice) { 189 | // 190 | // // after a valid response, the stimulus will have the CSS class 'responded' 191 | // // which can be used to provide visual feedback that a response was recorded 192 | // display_element.querySelector('#jspsych-html-button-response-stimulus').className += ' responded'; 193 | // 194 | // // disable all the buttons after a response 195 | // var btns = document.querySelectorAll('.jspsych-html-button-response-button button'); 196 | // for(var i=0; i 2 | 3 | WM Digit Span 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 237 | 238 | -------------------------------------------------------------------------------- /symmetry_span_task.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | WM symmetry span task 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 339 | 340 | -------------------------------------------------------------------------------- /operation_span_task.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | WM operation span task 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 371 | 372 | --------------------------------------------------------------------------------