Misc refactoring in JsPsych.ts

This commit is contained in:
bjoluc 2022-11-21 12:33:39 +01:00
parent 6d0689decb
commit 931a54b57a

View File

@ -32,42 +32,29 @@ export class JsPsych {
return version; return version;
} }
// /** Options */
// private variables
//
/**
* options
*/
private options: any = {}; private options: any = {};
/** /** Experiment timeline */
* experiment timeline
*/
private timeline?: Timeline; private timeline?: Timeline;
// target DOM element /** Target DOM element */
private domContainer: HTMLElement; private displayContainerElement: HTMLElement;
private domTarget: HTMLElement; private displayElement: HTMLElement;
/** /** Time that the experiment began */
* time that the experiment began
*/
private experimentStartTime: Date; private experimentStartTime: Date;
/** /**
* is the page retrieved directly via file:// protocol (true) or hosted on a server (false)? * Whether the page is retrieved directly via the `file://` protocol (true) or hosted on a web
* server (false)
*/ */
private file_protocol = false; private isFileProtocolUsed = false;
/** /** The simulation mode (if the experiment is being simulated) */
* The simulation mode if the experiment is being simulated
*/
private simulationMode?: SimulationMode; private simulationMode?: SimulationMode;
/** /** Simulation options passed in via `simulate()` */
* Simulation options passed in via `simulate()`
*/
private simulationOptions: Record<string, SimulationOptionsParameter>; private simulationOptions: Record<string, SimulationOptionsParameter>;
private extensionManager: ExtensionManager; private extensionManager: ExtensionManager;
@ -99,13 +86,14 @@ export class JsPsych {
autoBind(this); // so we can pass JsPsych methods as callbacks and `this` remains the JsPsych instance autoBind(this); // so we can pass JsPsych methods as callbacks and `this` remains the JsPsych instance
// detect whether page is running in browser as a local file, and if so, disable web audio and video preloading to prevent CORS issues // detect whether page is running in browser as a local file, and if so, disable web audio and
// video preloading to prevent CORS issues
if ( if (
window.location.protocol == "file:" && window.location.protocol == "file:" &&
(options.override_safe_mode === false || typeof options.override_safe_mode === "undefined") (options.override_safe_mode === false || typeof options.override_safe_mode === "undefined")
) { ) {
options.use_webaudio = false; options.use_webaudio = false;
this.file_protocol = true; this.isFileProtocolUsed = true;
console.warn( console.warn(
"jsPsych detected that it is running via the file:// protocol and not on a web server. " + "jsPsych detected that it is running via the file:// protocol and not on a web server. " +
"To prevent issues with cross-origin requests, Web Audio and video preloading have been disabled. " + "To prevent issues with cross-origin requests, Web Audio and video preloading have been disabled. " +
@ -134,7 +122,7 @@ export class JsPsych {
*/ */
async run(timeline: TimelineDescription | TimelineArray) { async run(timeline: TimelineDescription | TimelineArray) {
if (typeof timeline === "undefined") { if (typeof timeline === "undefined") {
console.error("No timeline declared in jsPsych.run. Cannot start experiment."); console.error("No timeline declared in jsPsych.run(). Cannot start experiment.");
} }
if (timeline.length === 0) { if (timeline.length === 0) {
@ -195,11 +183,11 @@ export class JsPsych {
} }
getDisplayElement() { getDisplayElement() {
return this.domTarget; return this.displayElement;
} }
getDisplayContainerElement() { getDisplayContainerElement() {
return this.domContainer; return this.displayContainerElement;
} }
abortExperiment(endMessage?: string, data = {}) { abortExperiment(endMessage?: string, data = {}) {
@ -250,13 +238,8 @@ export class JsPsych {
this.timeline?.resume(); this.timeline?.resume();
} }
private loadFail(message) {
message = message || "<p>The experiment failed to load.</p>";
this.domTarget.innerHTML = message;
}
getSafeModeStatus() { getSafeModeStatus() {
return this.file_protocol; return this.isFileProtocolUsed;
} }
getTimeline() { getTimeline() {
@ -281,18 +264,19 @@ export class JsPsych {
// if undefined, then jsPsych will use the <body> tag and the entire page // if undefined, then jsPsych will use the <body> tag and the entire page
if (typeof options.display_element === "undefined") { if (typeof options.display_element === "undefined") {
// check if there is a body element on the page // check if there is a body element on the page
const body = document.querySelector("body"); let body = document.body;
if (body === null) { if (!body) {
document.documentElement.appendChild(document.createElement("body")); body = document.createElement("body");
document.documentElement.appendChild(body);
} }
// using the full page, so we need the HTML element to // using the full page, so we need the HTML element to have 100% height, and body to be full
// have 100% height, and body to be full width and height with // width and height with no margin
// no margin
document.querySelector("html").style.height = "100%"; document.querySelector("html").style.height = "100%";
document.querySelector("body").style.margin = "0px";
document.querySelector("body").style.height = "100%"; body.style.margin = "0px";
document.querySelector("body").style.width = "100%"; body.style.height = "100%";
options.display_element = document.querySelector("body"); body.style.width = "100%";
options.display_element = body;
} else { } else {
// make sure that the display element exists on the page // make sure that the display element exists on the page
const display = const display =
@ -306,24 +290,28 @@ export class JsPsych {
} }
} }
options.display_element.innerHTML = const contentElement = document.createElement("div");
'<div class="jspsych-content-wrapper"><div id="jspsych-content"></div></div>'; contentElement.id = "jspsych-content";
this.domContainer = options.display_element;
this.domTarget = document.querySelector("#jspsych-content"); const contentWrapperElement = document.createElement("div");
contentWrapperElement.className = "jspsych-content-wrapper";
contentWrapperElement.appendChild(contentElement);
this.displayContainerElement = options.display_element;
this.displayContainerElement.appendChild(contentWrapperElement);
this.displayElement = contentElement;
// set experiment_width if not null // set experiment_width if not null
if (options.experiment_width !== null) { if (options.experiment_width !== null) {
this.domTarget.style.width = options.experiment_width + "px"; this.displayElement.style.width = options.experiment_width + "px";
} }
// add tabIndex attribute to scope event listeners // add tabIndex attribute to scope event listeners
options.display_element.tabIndex = 0; options.display_element.tabIndex = 0;
// add CSS class to DOM_target // Add CSS classes to container and display elements
if (options.display_element.className.indexOf("jspsych-display-element") === -1) { this.displayContainerElement.classList.add("jspsych-display-element");
options.display_element.className += " jspsych-display-element"; this.displayElement.classList.add("jspsych-content");
}
this.domTarget.className += "jspsych-content";
// create listeners for user browser interaction // create listeners for user browser interaction
this.data.createInteractionListeners(); this.data.createInteractionListeners();