/** * jspsych-preload * documentation: docs.jspsych.org **/ jsPsych.plugins['preload'] = (function() { var plugin = {}; plugin.info = { name: 'preload', description: '', parameters: { auto_preload: { type: jsPsych.plugins.parameterType.BOOL, default: false, description: 'Whether or not to automatically preload any media files based on the timeline passed to jsPsych.init.' }, trials: { type: jsPsych.plugins.parameterType.TIMELINE, default: [], description: 'Array with a timeline of trials to automatically preload. If one or more trial objects is provided, '+ 'then the plugin will attempt to preload the media files used in the trial(s).' }, images: { type: jsPsych.plugins.parameterType.STRING, default: [], description: 'Array with one or more image files to load. This parameter is often used in cases where media files cannot '+ 'be automatically preloaded based on the timeline, e.g. because the media files are passed into an image plugin/parameter with '+ 'timeline variables or dynamic parameters, or because the image is embedded in an HTML string.' }, audio: { type: jsPsych.plugins.parameterType.STRING, default: [], description: 'Array with one or more audio files to load. This parameter is often used in cases where media files cannot '+ 'be automatically preloaded based on the timeline, e.g. because the media files are passed into an audio plugin/parameter with '+ 'timeline variables or dynamic parameters, or because the audio is embedded in an HTML string.' }, video: { type: jsPsych.plugins.parameterType.STRING, default: [], description: 'Array with one or more video files to load. This parameter is often used in cases where media files cannot '+ 'be automatically preloaded based on the timeline, e.g. because the media files are passed into a video plugin/parameter with '+ 'timeline variables or dynamic parameters, or because the video is embedded in an HTML string.' }, message: { type: jsPsych.plugins.parameterType.HTML_STRING, default: null, description: 'HTML-formatted message to be shown above the progress bar while the files are loading.' }, show_progress_bar: { type: jsPsych.plugins.parameterType.BOOL, default: true, description: 'Whether or not to show the loading progress bar.' }, continue_after_error: { type: jsPsych.plugins.parameterType.BOOL, default: false, description: 'Whether or not to continue with the experiment if a loading error occurs. If false, then if a loading error occurs, '+ 'the error_message will be shown on the page and the trial will not end. If true, then if if a loading error occurs, the trial will end '+ 'and preloading failure will be logged in the trial data.' }, error_message: { type: jsPsych.plugins.parameterType.HTML_STRING, default: 'The experiment failed to load.', description: 'Error message to show on the page in case of any loading errors. This parameter is only relevant when continue_after_error is false.' }, show_detailed_errors: { type: jsPsych.plugins.parameterType.BOOL, default: false, description: 'Whether or not to show a detailed error message on the page. If true, then detailed error messages will be shown on the '+ 'page for all files that failed to load, along with the general error_message. This parameter is only relevant when continue_after_error is false.' }, max_load_time: { type: jsPsych.plugins.parameterType.INT, default: null, description: 'The maximum amount of time that the plugin should wait before stopping the preload and either ending the trial '+ '(if continue_after_error is true) or stopping the experiment with an error message (if continue_after_error is false). '+ 'If null, the plugin will wait indefintely for the files to load.' }, on_error: { type: jsPsych.plugins.parameterType.FUNCTION, default: null, description: 'Function to be called after a file fails to load. The function takes the file name as its only argument.' }, on_success: { type: jsPsych.plugins.parameterType.FUNCTION, default: null, description: 'Function to be called after a file loads successfully. The function takes the file name as its only argument.' } } } plugin.trial = function(display_element, trial) { var success = null; var timeout = false; var failed_images = []; var failed_audio = []; var failed_video = []; var detailed_errors = []; var in_safe_mode = jsPsych.getSafeModeStatus(); // create list of media to preload // var images = []; var audio = []; var video = []; if(trial.auto_preload){ var auto_preload = jsPsych.pluginAPI.getAutoPreloadList(); images = images.concat(auto_preload.images); audio = audio.concat(auto_preload.audio); video = video.concat(auto_preload.video); } if(trial.trials.length > 0){ var trial_preloads = jsPsych.pluginAPI.getAutoPreloadList(trial.trials); images = images.concat(trial_preloads.images); audio = audio.concat(trial_preloads.audio); video = video.concat(trial_preloads.video); } images = images.concat(trial.images); audio = audio.concat(trial.audio); video = video.concat(trial.video); images = jsPsych.utils.unique(jsPsych.utils.flatten(images)); audio = jsPsych.utils.unique(jsPsych.utils.flatten(audio)); video = jsPsych.utils.unique(jsPsych.utils.flatten(video)); if (in_safe_mode) { // don't preload video if in safe mode (experiment is running via file protocol) video = []; } // render display of message and progress bar var html = ''; if(trial.message !== null){ html += trial.message; } if(trial.show_progress_bar){ html += `
Error loading file: '+source+'
';
if (e.error.statusText) {
err_msg += 'File request response status: '+e.error.statusText+'
';
}
if (e.error == "404") {
err_msg += '404 - file not found.
';
}
if (typeof e.error.loaded !== 'undefined' && e.error.loaded !== null && e.error.loaded !== 0) {
err_msg += e.error.loaded+' bytes transferred.';
} else {
err_msg += 'File did not begin loading. Check that file path is correct and reachable by the browser,
'+
'and that loading is not blocked by cross-origin resource sharing (CORS) errors.';
}
err_msg += '
Loading timed out.
'+
'Consider compressing your stimuli files, loading your files in smaller batches,
'+
'and/or increasing the max_load_time parameter.
Error details:
'; detailed_errors.forEach(function(e) { display_element.innerHTML += e; }); } } function after_error(source) { // call on_error function and pass file name if (trial.on_error !== null) { trial.on_error(source); } } function after_success(source) { // call on_success function and pass file name if (trial.on_success !== null) { trial.on_success(source); } } function end_trial(){ // clear timeout again when end_trial is called, to handle race condition with max_load_time jsPsych.pluginAPI.clearAllTimeouts(); var trial_data = { success: success, timeout: timeout, failed_images: failed_images, failed_audio: failed_audio, failed_video: failed_video }; // clear the display display_element.innerHTML = ''; jsPsych.finishTrial(trial_data); } }; return plugin; })();