From d1382968f4a585161396a07076ee800e469f5d9d Mon Sep 17 00:00:00 2001 From: Shaobin-Jiang Date: Tue, 2 Jan 2024 21:59:07 +0800 Subject: [PATCH 1/8] allow message_progress_bar to be a function --- packages/jspsych/src/ProgressBar.ts | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/packages/jspsych/src/ProgressBar.ts b/packages/jspsych/src/ProgressBar.ts index d9168f1d62..5eb9655440 100644 --- a/packages/jspsych/src/ProgressBar.ts +++ b/packages/jspsych/src/ProgressBar.ts @@ -2,7 +2,10 @@ * Maintains a visual progress bar using HTML and CSS */ export class ProgressBar { - constructor(private readonly containerElement: HTMLDivElement, private readonly message: string) { + constructor( + private readonly containerElement: HTMLDivElement, + private readonly message: string | ((progress: number) => string) + ) { this.setupElements(); } @@ -14,7 +17,13 @@ export class ProgressBar { /** Adds the progress bar HTML code into `this.containerElement` */ private setupElements() { this.messageSpan = document.createElement("span"); - this.messageSpan.innerHTML = this.message; + + if (Object.prototype.toString.call(this.message) === "[object Function]") { + this.messageSpan.innerHTML = (this.message as (progress: number) => string)(0); + } else { + // Progress starts at 0 when experiment commences + this.messageSpan.innerHTML = this.message as string; + } this.innerDiv = document.createElement("div"); this.innerDiv.id = "jspsych-progressbar-inner"; @@ -31,6 +40,10 @@ export class ProgressBar { /** Updates the progress bar according to `this.progress` */ private update() { this.innerDiv.style.width = this._progress * 100 + "%"; + + if (Object.prototype.toString.call(this.message) === "[object Function]") { + this.messageSpan.innerHTML = (this.message as (progress: number) => string)(this._progress); + } } /** From ed9c268abe7a1ac961cae6efaea8574f23635495 Mon Sep 17 00:00:00 2001 From: Shaobin-Jiang Date: Tue, 2 Jan 2024 21:59:20 +0800 Subject: [PATCH 2/8] update doc for message_progress_bar --- docs/reference/jspsych.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/reference/jspsych.md b/docs/reference/jspsych.md index 7539e9ba9c..2dc987efe1 100644 --- a/docs/reference/jspsych.md +++ b/docs/reference/jspsych.md @@ -26,7 +26,7 @@ The settings object can contain several parameters. None of the parameters are r | on_close | function | Function to execute when the user leaves the page. Can be used, for example, to save data before the page is closed. | | exclusions | object | Specifies restrictions on the browser the participant can use to complete the experiment. See list of options below. *This feature is deprecated as of v7.1 and will be removed in v8.0. The [browser-check plugin](../plugins/browser-check.md) is an improved way to handle exclusions.* | | show_progress_bar | boolean | If `true`, then [a progress bar](../overview/progress-bar.md) is shown at the top of the page. Default is `false`. | -| message_progress_bar | string | Message to display next to the progress bar. The default is 'Completion Progress'. | +| message_progress_bar | string or function | Message to display next to the progress bar or a function that returns that message. The default is 'Completion Progress'. If `message_progress_bar` is a function, it receives one single argument which is the current progress, ranging from 0 to 1; the function gets called on every progress bar update automatically. | | auto_update_progress_bar | boolean | If true, then the progress bar at the top of the page will automatically update as every top-level timeline or trial is completed. | | use_webaudio | boolean | If false, then jsPsych will not attempt to use the WebAudio API for audio playback. Instead, HTML5 Audio objects will be used. The WebAudio API offers more precise control over the timing of audio events, and should be used when possible. The default value is `true`. | | default_iti | numeric | The default inter-trial interval in ms. The default value if none is specified is 0ms. | From be7df30379c66a6786443cff2e503acbdc239901 Mon Sep 17 00:00:00 2001 From: Shaobin-Jiang Date: Wed, 3 Jan 2024 09:43:45 +0800 Subject: [PATCH 3/8] add changeset --- .changeset/stupid-baboons-wait.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/stupid-baboons-wait.md diff --git a/.changeset/stupid-baboons-wait.md b/.changeset/stupid-baboons-wait.md new file mode 100644 index 0000000000..dda0329a5f --- /dev/null +++ b/.changeset/stupid-baboons-wait.md @@ -0,0 +1,5 @@ +--- +"jspsych": major +--- + +Allow message_progress_bar to be a function From 9727773036c93150b1253e480939d7b4d7cfc48e Mon Sep 17 00:00:00 2001 From: Shaobin-Jiang Date: Wed, 10 Jan 2024 13:57:37 +0800 Subject: [PATCH 4/8] fix changeset version --- .changeset/stupid-baboons-wait.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/stupid-baboons-wait.md b/.changeset/stupid-baboons-wait.md index dda0329a5f..a2477adb8f 100644 --- a/.changeset/stupid-baboons-wait.md +++ b/.changeset/stupid-baboons-wait.md @@ -1,5 +1,5 @@ --- -"jspsych": major +"jspsych": minor --- Allow message_progress_bar to be a function From 4dbdbc0e682da67c9dc0189d893b2711d7d18823 Mon Sep 17 00:00:00 2001 From: Shaobin-Jiang Date: Wed, 10 Jan 2024 13:58:13 +0800 Subject: [PATCH 5/8] refactor message updating - adding a private `updateMessage` method - using a simpler version of checking function type --- packages/jspsych/src/ProgressBar.ts | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/packages/jspsych/src/ProgressBar.ts b/packages/jspsych/src/ProgressBar.ts index 5eb9655440..cad6e30a8c 100644 --- a/packages/jspsych/src/ProgressBar.ts +++ b/packages/jspsych/src/ProgressBar.ts @@ -18,12 +18,7 @@ export class ProgressBar { private setupElements() { this.messageSpan = document.createElement("span"); - if (Object.prototype.toString.call(this.message) === "[object Function]") { - this.messageSpan.innerHTML = (this.message as (progress: number) => string)(0); - } else { - // Progress starts at 0 when experiment commences - this.messageSpan.innerHTML = this.message as string; - } + this.updateMessage(); this.innerDiv = document.createElement("div"); this.innerDiv.id = "jspsych-progressbar-inner"; @@ -41,8 +36,14 @@ export class ProgressBar { private update() { this.innerDiv.style.width = this._progress * 100 + "%"; - if (Object.prototype.toString.call(this.message) === "[object Function]") { - this.messageSpan.innerHTML = (this.message as (progress: number) => string)(this._progress); + this.updateMessage(); + } + + private updateMessage() { + if (typeof this.message === "function") { + this.messageSpan.innerHTML = this.message(0); + } else { + this.messageSpan.innerHTML = this.message; } } From f0439475b400b65b1a8b54229e7281e56ae9ba49 Mon Sep 17 00:00:00 2001 From: Shaobin-Jiang Date: Wed, 10 Jan 2024 14:22:20 +0800 Subject: [PATCH 6/8] fix updateMessage method --- packages/jspsych/src/ProgressBar.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/jspsych/src/ProgressBar.ts b/packages/jspsych/src/ProgressBar.ts index cad6e30a8c..d8a884343b 100644 --- a/packages/jspsych/src/ProgressBar.ts +++ b/packages/jspsych/src/ProgressBar.ts @@ -41,7 +41,7 @@ export class ProgressBar { private updateMessage() { if (typeof this.message === "function") { - this.messageSpan.innerHTML = this.message(0); + this.messageSpan.innerHTML = this.message(this._progress); } else { this.messageSpan.innerHTML = this.message; } From 9d1d30986f3071cbb603ab2e150cfdd426cffb49 Mon Sep 17 00:00:00 2001 From: Shaobin-Jiang Date: Wed, 10 Jan 2024 14:22:33 +0800 Subject: [PATCH 7/8] update unit test --- packages/jspsych/src/ProgressBar.spec.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/packages/jspsych/src/ProgressBar.spec.ts b/packages/jspsych/src/ProgressBar.spec.ts index 70dd2fd394..acefc985b7 100644 --- a/packages/jspsych/src/ProgressBar.spec.ts +++ b/packages/jspsych/src/ProgressBar.spec.ts @@ -44,5 +44,17 @@ describe("ProgressBar", () => { '"jsPsych.progressBar.progress must be a number between 0 and 1"' ); }); + + it("should work when message is a function", () => { + // Override default container element and progress bar + containerElement = document.createElement("div"); + progressBar = new ProgressBar(containerElement, (progress: number) => String(progress)); + let messageSpan: HTMLSpanElement = containerElement.querySelector("span"); + + expect(messageSpan.innerHTML).toEqual("0"); + + progressBar.progress = 0.5; + expect(messageSpan.innerHTML).toEqual("0.5"); + }); }); }); From 4cb77e885d4a7a2a288bf49973e7080743fd3cca Mon Sep 17 00:00:00 2001 From: Shaobin-Jiang Date: Tue, 16 Jan 2024 09:11:07 +0800 Subject: [PATCH 8/8] move `updateMessage` into `update` --- packages/jspsych/src/ProgressBar.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/packages/jspsych/src/ProgressBar.ts b/packages/jspsych/src/ProgressBar.ts index d8a884343b..f8196d4f71 100644 --- a/packages/jspsych/src/ProgressBar.ts +++ b/packages/jspsych/src/ProgressBar.ts @@ -18,8 +18,6 @@ export class ProgressBar { private setupElements() { this.messageSpan = document.createElement("span"); - this.updateMessage(); - this.innerDiv = document.createElement("div"); this.innerDiv.id = "jspsych-progressbar-inner"; this.update(); @@ -36,10 +34,6 @@ export class ProgressBar { private update() { this.innerDiv.style.width = this._progress * 100 + "%"; - this.updateMessage(); - } - - private updateMessage() { if (typeof this.message === "function") { this.messageSpan.innerHTML = this.message(this._progress); } else {