From dec9bef3821b9339e2af609e7fa0b489358a5e32 Mon Sep 17 00:00:00 2001 From: Josh de Leeuw Date: Mon, 16 Oct 2023 11:56:46 -0400 Subject: [PATCH 01/12] Add grid option, make it default --- examples/jspsych-html-button-response.html | 10 ++++- packages/jspsych/src/index.scss | 17 +++++++- .../plugin-html-button-response/src/index.ts | 39 ++++++++++++------- 3 files changed, 49 insertions(+), 17 deletions(-) diff --git a/examples/jspsych-html-button-response.html b/examples/jspsych-html-button-response.html index 6cce713788..39bdeeaf35 100644 --- a/examples/jspsych-html-button-response.html +++ b/examples/jspsych-html-button-response.html @@ -20,7 +20,15 @@ type: jsPsychHtmlButtonResponse, stimulus: '

GREEN

', choices: ['Green', 'Blue', 'Red'], - prompt: "

What color is this word?

" + prompt: "

What color is this word? (flex layout)

" + }); + + timeline.push({ + type: jsPsychHtmlButtonResponse, + stimulus: '

GREEN

', + choices: ['Green', 'Blue', 'Red'], + button_layout: "grid", + prompt: "

What color is this word? (grid layout)

" }); timeline.push({ diff --git a/packages/jspsych/src/index.scss b/packages/jspsych/src/index.scss index 5722a2b21e..4093c9824c 100644 --- a/packages/jspsych/src/index.scss +++ b/packages/jspsych/src/index.scss @@ -58,11 +58,24 @@ font-size: 14px; } +/* Buttons and Button Groups */ + +.jspsych-btn-group-flex { + display: flex; + justify-content: center; +} + +.jspsych-btn-group-grid { + display: grid; + grid-auto-columns: max-content; + min-width: fit-content; +} + /* borrowing Bootstrap style for btn elements, but combining styles a bit */ .jspsych-btn { display: inline-block; - padding: 6px 12px; - margin: 0px; + padding: 8px 12px; + margin: 0.75em; font-size: 14px; font-weight: 400; font-family: "Open Sans", "Arial", sans-serif; diff --git a/packages/plugin-html-button-response/src/index.ts b/packages/plugin-html-button-response/src/index.ts index 0c3c33a213..1ec684a3f7 100644 --- a/packages/plugin-html-button-response/src/index.ts +++ b/packages/plugin-html-button-response/src/index.ts @@ -45,17 +45,25 @@ const info = { pretty_name: "Trial duration", default: null, }, - /** The vertical margin of the button. */ - margin_vertical: { + /** The CSS layout for the buttons. Options: 'flex' or 'grid'. */ + button_layout: { type: ParameterType.STRING, - pretty_name: "Margin vertical", - default: "0px", + pretty_name: "Button layout", + default: "grid", }, - /** The horizontal margin of the button. */ - margin_horizontal: { + /** The number of grid rows when `button_layout` is "grid" */ + button_rows: { type: ParameterType.STRING, - pretty_name: "Margin horizontal", - default: "8px", + pretty_name: "Grid rows", + default: "1", + }, + /** The number of grid columns when `button_layout` is "grid". + * Using "auto" will make the number of columns equal the number + * of buttons. */ + button_cols: { + type: ParameterType.STRING, + pretty_name: "Grid columns", + default: "auto", }, /** If true, then trial will end when user responds. */ response_ends_trial: { @@ -90,12 +98,15 @@ class HtmlButtonResponsePlugin implements JsPsychPlugin { // Display buttons const buttonGroupElement = document.createElement("div"); buttonGroupElement.id = "jspsych-html-button-response-btngroup"; - buttonGroupElement.style.cssText = ` - display: flex; - justify-content: center; - gap: ${trial.margin_vertical} ${trial.margin_horizontal}; - padding: ${trial.margin_vertical} ${trial.margin_horizontal}; - `; + if (trial.button_layout === "grid") { + buttonGroupElement.classList.add("jspsych-btn-group-grid"); + let n_cols = + trial.button_cols === "auto" ? trial.choices.length : parseInt(trial.button_cols); + buttonGroupElement.style.gridTemplateColumns = `repeat(${n_cols}, 1fr)`; + buttonGroupElement.style.gridTemplateRows = `repeat(${trial.button_rows}, 1fr)`; + } else if (trial.button_layout === "flex") { + buttonGroupElement.classList.add("jspsych-btn-group-flex"); + } for (const [choiceIndex, choice] of trial.choices.entries()) { buttonGroupElement.insertAdjacentHTML("beforeend", trial.button_html(choice, choiceIndex)); From 49988259802e8f946dc6dc1db39d49a1e76af54a Mon Sep 17 00:00:00 2001 From: Josh de Leeuw Date: Wed, 18 Oct 2023 14:42:46 -0400 Subject: [PATCH 02/12] change how rows and cols are calculated, change css layout, add example --- examples/jspsych-html-button-response.html | 10 ++++++ packages/jspsych/src/index.scss | 4 ++- .../plugin-html-button-response/src/index.ts | 34 +++++++++++++------ 3 files changed, 37 insertions(+), 11 deletions(-) diff --git a/examples/jspsych-html-button-response.html b/examples/jspsych-html-button-response.html index 39bdeeaf35..99db2e3a4e 100644 --- a/examples/jspsych-html-button-response.html +++ b/examples/jspsych-html-button-response.html @@ -20,6 +20,7 @@ type: jsPsychHtmlButtonResponse, stimulus: '

GREEN

', choices: ['Green', 'Blue', 'Red'], + button_layout: "flex", prompt: "

What color is this word? (flex layout)

" }); @@ -31,6 +32,15 @@ prompt: "

What color is this word? (grid layout)

" }); + timeline.push({ + type: jsPsychHtmlButtonResponse, + stimulus: '

GREEN

', + choices: ['Green', 'Blue', 'Red'], + button_layout: "grid", + button_rows: 2, + prompt: "

What color is this word? (grid layout, two rows)

" + }); + timeline.push({ type: jsPsychHtmlButtonResponse, stimulus: '

GREEN

', diff --git a/packages/jspsych/src/index.scss b/packages/jspsych/src/index.scss index 4093c9824c..4b6ab3ba4d 100644 --- a/packages/jspsych/src/index.scss +++ b/packages/jspsych/src/index.scss @@ -68,7 +68,9 @@ .jspsych-btn-group-grid { display: grid; grid-auto-columns: max-content; - min-width: fit-content; + max-width: fit-content; + margin-right: auto; + margin-left: auto; } /* borrowing Bootstrap style for btn elements, but combining styles a bit */ diff --git a/packages/plugin-html-button-response/src/index.ts b/packages/plugin-html-button-response/src/index.ts index 1ec684a3f7..1f5d61639b 100644 --- a/packages/plugin-html-button-response/src/index.ts +++ b/packages/plugin-html-button-response/src/index.ts @@ -51,19 +51,22 @@ const info = { pretty_name: "Button layout", default: "grid", }, - /** The number of grid rows when `button_layout` is "grid" */ + /** The number of grid rows when `button_layout` is "grid". + * Setting to `null` will infer the number of rows based on the + * number of columns and buttons. + */ button_rows: { - type: ParameterType.STRING, + type: ParameterType.INT, pretty_name: "Grid rows", - default: "1", + default: 1, }, /** The number of grid columns when `button_layout` is "grid". - * Using "auto" will make the number of columns equal the number - * of buttons. */ + * Setting to `null` (default value) will infer the number of columns + * based on the number of rows and buttons. */ button_cols: { - type: ParameterType.STRING, + type: ParameterType.INT, pretty_name: "Grid columns", - default: "auto", + default: null, }, /** If true, then trial will end when user responds. */ response_ends_trial: { @@ -100,10 +103,21 @@ class HtmlButtonResponsePlugin implements JsPsychPlugin { buttonGroupElement.id = "jspsych-html-button-response-btngroup"; if (trial.button_layout === "grid") { buttonGroupElement.classList.add("jspsych-btn-group-grid"); - let n_cols = - trial.button_cols === "auto" ? trial.choices.length : parseInt(trial.button_cols); + if (trial.button_rows === null && trial.button_cols === null) { + throw new Error( + "You must specify the number of rows or columns when using the grid layout." + ); + } + const n_cols = + trial.button_cols === null + ? Math.ceil(trial.choices.length / trial.button_rows) + : trial.button_cols; + const n_rows = + trial.button_rows === null + ? Math.ceil(trial.choices.length / trial.button_cols) + : trial.button_rows; buttonGroupElement.style.gridTemplateColumns = `repeat(${n_cols}, 1fr)`; - buttonGroupElement.style.gridTemplateRows = `repeat(${trial.button_rows}, 1fr)`; + buttonGroupElement.style.gridTemplateRows = `repeat(${n_rows}, 1fr)`; } else if (trial.button_layout === "flex") { buttonGroupElement.classList.add("jspsych-btn-group-flex"); } From 2852cda642c6b1cfc0427049dfc6dfb321d9e27f Mon Sep 17 00:00:00 2001 From: Josh de Leeuw Date: Wed, 18 Oct 2023 14:47:59 -0400 Subject: [PATCH 03/12] add changeset --- .changeset/button-layouts.md | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 .changeset/button-layouts.md diff --git a/.changeset/button-layouts.md b/.changeset/button-layouts.md new file mode 100644 index 0000000000..47ff1df98a --- /dev/null +++ b/.changeset/button-layouts.md @@ -0,0 +1,8 @@ +--- +"@jspsych/plugin-html-button-response": major +"jspsych": patch +--- + +Button plugins now support either `display: grid` or `display: flex` on the container element that hold the buttons. If the layout is `grid`, the number of rows and/or columns can be specified. + +jspsych.css has new layout classes to support this feature. From ed99076c3c87f1b3c8c4c9b3a6ae61fe5d1d4540 Mon Sep 17 00:00:00 2001 From: Josh de Leeuw Date: Wed, 18 Oct 2023 15:00:00 -0400 Subject: [PATCH 04/12] implements modifications in all button response plugins --- .../plugin-audio-button-response/src/index.ts | 57 +++++++++++++------ .../src/index.ts | 57 +++++++++++++------ .../plugin-image-button-response/src/index.ts | 57 +++++++++++++------ .../plugin-video-button-response/src/index.ts | 57 +++++++++++++------ 4 files changed, 164 insertions(+), 64 deletions(-) diff --git a/packages/plugin-audio-button-response/src/index.ts b/packages/plugin-audio-button-response/src/index.ts index 01ca810833..5a0c52d121 100644 --- a/packages/plugin-audio-button-response/src/index.ts +++ b/packages/plugin-audio-button-response/src/index.ts @@ -39,17 +39,28 @@ const info = { pretty_name: "Trial duration", default: null, }, - /** Vertical margin of button. */ - margin_vertical: { + /** The CSS layout for the buttons. Options: 'flex' or 'grid'. */ + button_layout: { type: ParameterType.STRING, - pretty_name: "Margin vertical", - default: "0px", + pretty_name: "Button layout", + default: "grid", }, - /** Horizontal margin of button. */ - margin_horizontal: { - type: ParameterType.STRING, - pretty_name: "Margin horizontal", - default: "8px", + /** The number of grid rows when `button_layout` is "grid". + * Setting to `null` will infer the number of rows based on the + * number of columns and buttons. + */ + button_rows: { + type: ParameterType.INT, + pretty_name: "Grid rows", + default: 1, + }, + /** The number of grid columns when `button_layout` is "grid". + * Setting to `null` (default value) will infer the number of columns + * based on the number of rows and buttons. */ + button_cols: { + type: ParameterType.INT, + pretty_name: "Grid columns", + default: null, }, /** If true, the trial will end when user makes a response. */ response_ends_trial: { @@ -143,13 +154,27 @@ class AudioButtonResponsePlugin implements JsPsychPlugin { // Display buttons const buttonGroupElement = document.createElement("div"); - buttonGroupElement.id = "jspsych-audio-button-response-btngroup"; - buttonGroupElement.style.cssText = ` - display: flex; - justify-content: center; - gap: ${trial.margin_vertical} ${trial.margin_horizontal}; - padding: ${trial.margin_vertical} ${trial.margin_horizontal}; - `; + buttonGroupElement.id = "jspsych-html-button-response-btngroup"; + if (trial.button_layout === "grid") { + buttonGroupElement.classList.add("jspsych-btn-group-grid"); + if (trial.button_rows === null && trial.button_cols === null) { + throw new Error( + "You must specify the number of rows or columns when using the grid layout." + ); + } + const n_cols = + trial.button_cols === null + ? Math.ceil(trial.choices.length / trial.button_rows) + : trial.button_cols; + const n_rows = + trial.button_rows === null + ? Math.ceil(trial.choices.length / trial.button_cols) + : trial.button_rows; + buttonGroupElement.style.gridTemplateColumns = `repeat(${n_cols}, 1fr)`; + buttonGroupElement.style.gridTemplateRows = `repeat(${n_rows}, 1fr)`; + } else if (trial.button_layout === "flex") { + buttonGroupElement.classList.add("jspsych-btn-group-flex"); + } for (const [choiceIndex, choice] of trial.choices.entries()) { buttonGroupElement.insertAdjacentHTML("beforeend", trial.button_html(choice, choiceIndex)); diff --git a/packages/plugin-canvas-button-response/src/index.ts b/packages/plugin-canvas-button-response/src/index.ts index 095dbdfc1e..d82683a0b0 100644 --- a/packages/plugin-canvas-button-response/src/index.ts +++ b/packages/plugin-canvas-button-response/src/index.ts @@ -45,17 +45,28 @@ const info = { pretty_name: "Trial duration", default: null, }, - /** The vertical margin of the button. */ - margin_vertical: { + /** The CSS layout for the buttons. Options: 'flex' or 'grid'. */ + button_layout: { type: ParameterType.STRING, - pretty_name: "Margin vertical", - default: "0px", + pretty_name: "Button layout", + default: "grid", }, - /** The horizontal margin of the button. */ - margin_horizontal: { - type: ParameterType.STRING, - pretty_name: "Margin horizontal", - default: "8px", + /** The number of grid rows when `button_layout` is "grid". + * Setting to `null` will infer the number of rows based on the + * number of columns and buttons. + */ + button_rows: { + type: ParameterType.INT, + pretty_name: "Grid rows", + default: 1, + }, + /** The number of grid columns when `button_layout` is "grid". + * Setting to `null` (default value) will infer the number of columns + * based on the number of rows and buttons. */ + button_cols: { + type: ParameterType.INT, + pretty_name: "Grid columns", + default: null, }, /** If true, then trial will end when user responds. */ response_ends_trial: { @@ -103,13 +114,27 @@ class CanvasButtonResponsePlugin implements JsPsychPlugin { // Display buttons const buttonGroupElement = document.createElement("div"); - buttonGroupElement.id = "jspsych-canvas-button-response-btngroup"; - buttonGroupElement.style.cssText = ` - display: flex; - justify-content: center; - gap: ${trial.margin_vertical} ${trial.margin_horizontal}; - padding: ${trial.margin_vertical} ${trial.margin_horizontal}; - `; + buttonGroupElement.id = "jspsych-html-button-response-btngroup"; + if (trial.button_layout === "grid") { + buttonGroupElement.classList.add("jspsych-btn-group-grid"); + if (trial.button_rows === null && trial.button_cols === null) { + throw new Error( + "You must specify the number of rows or columns when using the grid layout." + ); + } + const n_cols = + trial.button_cols === null + ? Math.ceil(trial.choices.length / trial.button_rows) + : trial.button_cols; + const n_rows = + trial.button_rows === null + ? Math.ceil(trial.choices.length / trial.button_cols) + : trial.button_rows; + buttonGroupElement.style.gridTemplateColumns = `repeat(${n_cols}, 1fr)`; + buttonGroupElement.style.gridTemplateRows = `repeat(${n_rows}, 1fr)`; + } else if (trial.button_layout === "flex") { + buttonGroupElement.classList.add("jspsych-btn-group-flex"); + } for (const [choiceIndex, choice] of trial.choices.entries()) { buttonGroupElement.insertAdjacentHTML("beforeend", trial.button_html(choice, choiceIndex)); diff --git a/packages/plugin-image-button-response/src/index.ts b/packages/plugin-image-button-response/src/index.ts index b3ad193e67..0d3040ffe7 100644 --- a/packages/plugin-image-button-response/src/index.ts +++ b/packages/plugin-image-button-response/src/index.ts @@ -63,17 +63,28 @@ const info = { pretty_name: "Trial duration", default: null, }, - /** The vertical margin of the button. */ - margin_vertical: { + /** The CSS layout for the buttons. Options: 'flex' or 'grid'. */ + button_layout: { type: ParameterType.STRING, - pretty_name: "Margin vertical", - default: "0px", + pretty_name: "Button layout", + default: "grid", }, - /** The horizontal margin of the button. */ - margin_horizontal: { - type: ParameterType.STRING, - pretty_name: "Margin horizontal", - default: "8px", + /** The number of grid rows when `button_layout` is "grid". + * Setting to `null` will infer the number of rows based on the + * number of columns and buttons. + */ + button_rows: { + type: ParameterType.INT, + pretty_name: "Grid rows", + default: 1, + }, + /** The number of grid columns when `button_layout` is "grid". + * Setting to `null` (default value) will infer the number of columns + * based on the number of rows and buttons. */ + button_cols: { + type: ParameterType.INT, + pretty_name: "Grid columns", + default: null, }, /** If true, then trial will end when user responds. */ response_ends_trial: { @@ -184,13 +195,27 @@ class ImageButtonResponsePlugin implements JsPsychPlugin { // Display buttons const buttonGroupElement = document.createElement("div"); - buttonGroupElement.id = "jspsych-image-button-response-btngroup"; - buttonGroupElement.style.cssText = ` - display: flex; - justify-content: center; - gap: ${trial.margin_vertical} ${trial.margin_horizontal}; - padding: ${trial.margin_vertical} ${trial.margin_horizontal}; - `; + buttonGroupElement.id = "jspsych-html-button-response-btngroup"; + if (trial.button_layout === "grid") { + buttonGroupElement.classList.add("jspsych-btn-group-grid"); + if (trial.button_rows === null && trial.button_cols === null) { + throw new Error( + "You must specify the number of rows or columns when using the grid layout." + ); + } + const n_cols = + trial.button_cols === null + ? Math.ceil(trial.choices.length / trial.button_rows) + : trial.button_cols; + const n_rows = + trial.button_rows === null + ? Math.ceil(trial.choices.length / trial.button_cols) + : trial.button_rows; + buttonGroupElement.style.gridTemplateColumns = `repeat(${n_cols}, 1fr)`; + buttonGroupElement.style.gridTemplateRows = `repeat(${n_rows}, 1fr)`; + } else if (trial.button_layout === "flex") { + buttonGroupElement.classList.add("jspsych-btn-group-flex"); + } for (const [choiceIndex, choice] of trial.choices.entries()) { buttonGroupElement.insertAdjacentHTML("beforeend", trial.button_html(choice, choiceIndex)); diff --git a/packages/plugin-video-button-response/src/index.ts b/packages/plugin-video-button-response/src/index.ts index 48403bc3ed..5eac45d681 100644 --- a/packages/plugin-video-button-response/src/index.ts +++ b/packages/plugin-video-button-response/src/index.ts @@ -88,17 +88,28 @@ const info = { pretty_name: "Trial duration", default: null, }, - /** The vertical margin of the button. */ - margin_vertical: { + /** The CSS layout for the buttons. Options: 'flex' or 'grid'. */ + button_layout: { type: ParameterType.STRING, - pretty_name: "Margin vertical", - default: "0px", + pretty_name: "Button layout", + default: "grid", }, - /** The horizontal margin of the button. */ - margin_horizontal: { - type: ParameterType.STRING, - pretty_name: "Margin horizontal", - default: "8px", + /** The number of grid rows when `button_layout` is "grid". + * Setting to `null` will infer the number of rows based on the + * number of columns and buttons. + */ + button_rows: { + type: ParameterType.INT, + pretty_name: "Grid rows", + default: 1, + }, + /** The number of grid columns when `button_layout` is "grid". + * Setting to `null` (default value) will infer the number of columns + * based on the number of rows and buttons. */ + button_cols: { + type: ParameterType.INT, + pretty_name: "Grid columns", + default: null, }, /** If true, the trial will end when subject makes a response. */ response_ends_trial: { @@ -182,13 +193,27 @@ class VideoButtonResponsePlugin implements JsPsychPlugin { // Display buttons const buttonGroupElement = document.createElement("div"); - buttonGroupElement.id = "jspsych-video-button-response-btngroup"; - buttonGroupElement.style.cssText = ` - display: flex; - justify-content: center; - gap: ${trial.margin_vertical} ${trial.margin_horizontal}; - padding: ${trial.margin_vertical} ${trial.margin_horizontal}; - `; + buttonGroupElement.id = "jspsych-html-button-response-btngroup"; + if (trial.button_layout === "grid") { + buttonGroupElement.classList.add("jspsych-btn-group-grid"); + if (trial.button_rows === null && trial.button_cols === null) { + throw new Error( + "You must specify the number of rows or columns when using the grid layout." + ); + } + const n_cols = + trial.button_cols === null + ? Math.ceil(trial.choices.length / trial.button_rows) + : trial.button_cols; + const n_rows = + trial.button_rows === null + ? Math.ceil(trial.choices.length / trial.button_cols) + : trial.button_rows; + buttonGroupElement.style.gridTemplateColumns = `repeat(${n_cols}, 1fr)`; + buttonGroupElement.style.gridTemplateRows = `repeat(${n_rows}, 1fr)`; + } else if (trial.button_layout === "flex") { + buttonGroupElement.classList.add("jspsych-btn-group-flex"); + } for (const [choiceIndex, choice] of trial.choices.entries()) { buttonGroupElement.insertAdjacentHTML("beforeend", trial.button_html(choice, choiceIndex)); From 11e0103678142596cd9c8d2f91108e4efea8c7fa Mon Sep 17 00:00:00 2001 From: Josh de Leeuw Date: Wed, 18 Oct 2023 15:02:41 -0400 Subject: [PATCH 05/12] `button_rows` -> `grid_rows`; `button_cols` -> `grid_columns` --- examples/jspsych-html-button-response.html | 2 +- .../plugin-audio-button-response/src/index.ts | 18 +++++++++--------- .../plugin-canvas-button-response/src/index.ts | 18 +++++++++--------- .../plugin-html-button-response/src/index.ts | 18 +++++++++--------- .../plugin-image-button-response/src/index.ts | 18 +++++++++--------- .../plugin-video-button-response/src/index.ts | 18 +++++++++--------- 6 files changed, 46 insertions(+), 46 deletions(-) diff --git a/examples/jspsych-html-button-response.html b/examples/jspsych-html-button-response.html index 99db2e3a4e..b725081171 100644 --- a/examples/jspsych-html-button-response.html +++ b/examples/jspsych-html-button-response.html @@ -37,7 +37,7 @@ stimulus: '

GREEN

', choices: ['Green', 'Blue', 'Red'], button_layout: "grid", - button_rows: 2, + grid_rows: 2, prompt: "

What color is this word? (grid layout, two rows)

" }); diff --git a/packages/plugin-audio-button-response/src/index.ts b/packages/plugin-audio-button-response/src/index.ts index 5a0c52d121..fb84c7a321 100644 --- a/packages/plugin-audio-button-response/src/index.ts +++ b/packages/plugin-audio-button-response/src/index.ts @@ -49,7 +49,7 @@ const info = { * Setting to `null` will infer the number of rows based on the * number of columns and buttons. */ - button_rows: { + grid_rows: { type: ParameterType.INT, pretty_name: "Grid rows", default: 1, @@ -57,7 +57,7 @@ const info = { /** The number of grid columns when `button_layout` is "grid". * Setting to `null` (default value) will infer the number of columns * based on the number of rows and buttons. */ - button_cols: { + grid_columns: { type: ParameterType.INT, pretty_name: "Grid columns", default: null, @@ -157,19 +157,19 @@ class AudioButtonResponsePlugin implements JsPsychPlugin { buttonGroupElement.id = "jspsych-html-button-response-btngroup"; if (trial.button_layout === "grid") { buttonGroupElement.classList.add("jspsych-btn-group-grid"); - if (trial.button_rows === null && trial.button_cols === null) { + if (trial.grid_rows === null && trial.grid_columns === null) { throw new Error( "You must specify the number of rows or columns when using the grid layout." ); } const n_cols = - trial.button_cols === null - ? Math.ceil(trial.choices.length / trial.button_rows) - : trial.button_cols; + trial.grid_columns === null + ? Math.ceil(trial.choices.length / trial.grid_rows) + : trial.grid_columns; const n_rows = - trial.button_rows === null - ? Math.ceil(trial.choices.length / trial.button_cols) - : trial.button_rows; + trial.grid_rows === null + ? Math.ceil(trial.choices.length / trial.grid_columns) + : trial.grid_rows; buttonGroupElement.style.gridTemplateColumns = `repeat(${n_cols}, 1fr)`; buttonGroupElement.style.gridTemplateRows = `repeat(${n_rows}, 1fr)`; } else if (trial.button_layout === "flex") { diff --git a/packages/plugin-canvas-button-response/src/index.ts b/packages/plugin-canvas-button-response/src/index.ts index d82683a0b0..6de197694f 100644 --- a/packages/plugin-canvas-button-response/src/index.ts +++ b/packages/plugin-canvas-button-response/src/index.ts @@ -55,7 +55,7 @@ const info = { * Setting to `null` will infer the number of rows based on the * number of columns and buttons. */ - button_rows: { + grid_rows: { type: ParameterType.INT, pretty_name: "Grid rows", default: 1, @@ -63,7 +63,7 @@ const info = { /** The number of grid columns when `button_layout` is "grid". * Setting to `null` (default value) will infer the number of columns * based on the number of rows and buttons. */ - button_cols: { + grid_columns: { type: ParameterType.INT, pretty_name: "Grid columns", default: null, @@ -117,19 +117,19 @@ class CanvasButtonResponsePlugin implements JsPsychPlugin { buttonGroupElement.id = "jspsych-html-button-response-btngroup"; if (trial.button_layout === "grid") { buttonGroupElement.classList.add("jspsych-btn-group-grid"); - if (trial.button_rows === null && trial.button_cols === null) { + if (trial.grid_rows === null && trial.grid_columns === null) { throw new Error( "You must specify the number of rows or columns when using the grid layout." ); } const n_cols = - trial.button_cols === null - ? Math.ceil(trial.choices.length / trial.button_rows) - : trial.button_cols; + trial.grid_columns === null + ? Math.ceil(trial.choices.length / trial.grid_rows) + : trial.grid_columns; const n_rows = - trial.button_rows === null - ? Math.ceil(trial.choices.length / trial.button_cols) - : trial.button_rows; + trial.grid_rows === null + ? Math.ceil(trial.choices.length / trial.grid_columns) + : trial.grid_rows; buttonGroupElement.style.gridTemplateColumns = `repeat(${n_cols}, 1fr)`; buttonGroupElement.style.gridTemplateRows = `repeat(${n_rows}, 1fr)`; } else if (trial.button_layout === "flex") { diff --git a/packages/plugin-html-button-response/src/index.ts b/packages/plugin-html-button-response/src/index.ts index 1f5d61639b..aa07fc80ea 100644 --- a/packages/plugin-html-button-response/src/index.ts +++ b/packages/plugin-html-button-response/src/index.ts @@ -55,7 +55,7 @@ const info = { * Setting to `null` will infer the number of rows based on the * number of columns and buttons. */ - button_rows: { + grid_rows: { type: ParameterType.INT, pretty_name: "Grid rows", default: 1, @@ -63,7 +63,7 @@ const info = { /** The number of grid columns when `button_layout` is "grid". * Setting to `null` (default value) will infer the number of columns * based on the number of rows and buttons. */ - button_cols: { + grid_columns: { type: ParameterType.INT, pretty_name: "Grid columns", default: null, @@ -103,19 +103,19 @@ class HtmlButtonResponsePlugin implements JsPsychPlugin { buttonGroupElement.id = "jspsych-html-button-response-btngroup"; if (trial.button_layout === "grid") { buttonGroupElement.classList.add("jspsych-btn-group-grid"); - if (trial.button_rows === null && trial.button_cols === null) { + if (trial.grid_rows === null && trial.grid_columns === null) { throw new Error( "You must specify the number of rows or columns when using the grid layout." ); } const n_cols = - trial.button_cols === null - ? Math.ceil(trial.choices.length / trial.button_rows) - : trial.button_cols; + trial.grid_columns === null + ? Math.ceil(trial.choices.length / trial.grid_rows) + : trial.grid_columns; const n_rows = - trial.button_rows === null - ? Math.ceil(trial.choices.length / trial.button_cols) - : trial.button_rows; + trial.grid_rows === null + ? Math.ceil(trial.choices.length / trial.grid_columns) + : trial.grid_rows; buttonGroupElement.style.gridTemplateColumns = `repeat(${n_cols}, 1fr)`; buttonGroupElement.style.gridTemplateRows = `repeat(${n_rows}, 1fr)`; } else if (trial.button_layout === "flex") { diff --git a/packages/plugin-image-button-response/src/index.ts b/packages/plugin-image-button-response/src/index.ts index 0d3040ffe7..d487cb1460 100644 --- a/packages/plugin-image-button-response/src/index.ts +++ b/packages/plugin-image-button-response/src/index.ts @@ -73,7 +73,7 @@ const info = { * Setting to `null` will infer the number of rows based on the * number of columns and buttons. */ - button_rows: { + grid_rows: { type: ParameterType.INT, pretty_name: "Grid rows", default: 1, @@ -81,7 +81,7 @@ const info = { /** The number of grid columns when `button_layout` is "grid". * Setting to `null` (default value) will infer the number of columns * based on the number of rows and buttons. */ - button_cols: { + grid_columns: { type: ParameterType.INT, pretty_name: "Grid columns", default: null, @@ -198,19 +198,19 @@ class ImageButtonResponsePlugin implements JsPsychPlugin { buttonGroupElement.id = "jspsych-html-button-response-btngroup"; if (trial.button_layout === "grid") { buttonGroupElement.classList.add("jspsych-btn-group-grid"); - if (trial.button_rows === null && trial.button_cols === null) { + if (trial.grid_rows === null && trial.grid_columns === null) { throw new Error( "You must specify the number of rows or columns when using the grid layout." ); } const n_cols = - trial.button_cols === null - ? Math.ceil(trial.choices.length / trial.button_rows) - : trial.button_cols; + trial.grid_columns === null + ? Math.ceil(trial.choices.length / trial.grid_rows) + : trial.grid_columns; const n_rows = - trial.button_rows === null - ? Math.ceil(trial.choices.length / trial.button_cols) - : trial.button_rows; + trial.grid_rows === null + ? Math.ceil(trial.choices.length / trial.grid_columns) + : trial.grid_rows; buttonGroupElement.style.gridTemplateColumns = `repeat(${n_cols}, 1fr)`; buttonGroupElement.style.gridTemplateRows = `repeat(${n_rows}, 1fr)`; } else if (trial.button_layout === "flex") { diff --git a/packages/plugin-video-button-response/src/index.ts b/packages/plugin-video-button-response/src/index.ts index 5eac45d681..5828ee85de 100644 --- a/packages/plugin-video-button-response/src/index.ts +++ b/packages/plugin-video-button-response/src/index.ts @@ -98,7 +98,7 @@ const info = { * Setting to `null` will infer the number of rows based on the * number of columns and buttons. */ - button_rows: { + grid_rows: { type: ParameterType.INT, pretty_name: "Grid rows", default: 1, @@ -106,7 +106,7 @@ const info = { /** The number of grid columns when `button_layout` is "grid". * Setting to `null` (default value) will infer the number of columns * based on the number of rows and buttons. */ - button_cols: { + grid_columns: { type: ParameterType.INT, pretty_name: "Grid columns", default: null, @@ -196,19 +196,19 @@ class VideoButtonResponsePlugin implements JsPsychPlugin { buttonGroupElement.id = "jspsych-html-button-response-btngroup"; if (trial.button_layout === "grid") { buttonGroupElement.classList.add("jspsych-btn-group-grid"); - if (trial.button_rows === null && trial.button_cols === null) { + if (trial.grid_rows === null && trial.grid_columns === null) { throw new Error( "You must specify the number of rows or columns when using the grid layout." ); } const n_cols = - trial.button_cols === null - ? Math.ceil(trial.choices.length / trial.button_rows) - : trial.button_cols; + trial.grid_columns === null + ? Math.ceil(trial.choices.length / trial.grid_rows) + : trial.grid_columns; const n_rows = - trial.button_rows === null - ? Math.ceil(trial.choices.length / trial.button_cols) - : trial.button_rows; + trial.grid_rows === null + ? Math.ceil(trial.choices.length / trial.grid_columns) + : trial.grid_rows; buttonGroupElement.style.gridTemplateColumns = `repeat(${n_cols}, 1fr)`; buttonGroupElement.style.gridTemplateRows = `repeat(${n_rows}, 1fr)`; } else if (trial.button_layout === "flex") { From 808e835306297e73b38bd2dbe52a1c09dbc26331 Mon Sep 17 00:00:00 2001 From: Josh de Leeuw Date: Wed, 18 Oct 2023 15:05:15 -0400 Subject: [PATCH 06/12] use clearer error message when rows and columns both null --- packages/plugin-audio-button-response/src/index.ts | 2 +- packages/plugin-canvas-button-response/src/index.ts | 2 +- packages/plugin-html-button-response/src/index.ts | 2 +- packages/plugin-image-button-response/src/index.ts | 2 +- packages/plugin-video-button-response/src/index.ts | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/plugin-audio-button-response/src/index.ts b/packages/plugin-audio-button-response/src/index.ts index fb84c7a321..ec71a52437 100644 --- a/packages/plugin-audio-button-response/src/index.ts +++ b/packages/plugin-audio-button-response/src/index.ts @@ -159,7 +159,7 @@ class AudioButtonResponsePlugin implements JsPsychPlugin { buttonGroupElement.classList.add("jspsych-btn-group-grid"); if (trial.grid_rows === null && trial.grid_columns === null) { throw new Error( - "You must specify the number of rows or columns when using the grid layout." + "You cannot set `grid_rows` to `null` without providing a value for `grid_columns`." ); } const n_cols = diff --git a/packages/plugin-canvas-button-response/src/index.ts b/packages/plugin-canvas-button-response/src/index.ts index 6de197694f..a8350250ae 100644 --- a/packages/plugin-canvas-button-response/src/index.ts +++ b/packages/plugin-canvas-button-response/src/index.ts @@ -119,7 +119,7 @@ class CanvasButtonResponsePlugin implements JsPsychPlugin { buttonGroupElement.classList.add("jspsych-btn-group-grid"); if (trial.grid_rows === null && trial.grid_columns === null) { throw new Error( - "You must specify the number of rows or columns when using the grid layout." + "You cannot set `grid_rows` to `null` without providing a value for `grid_columns`." ); } const n_cols = diff --git a/packages/plugin-html-button-response/src/index.ts b/packages/plugin-html-button-response/src/index.ts index aa07fc80ea..0556f87523 100644 --- a/packages/plugin-html-button-response/src/index.ts +++ b/packages/plugin-html-button-response/src/index.ts @@ -105,7 +105,7 @@ class HtmlButtonResponsePlugin implements JsPsychPlugin { buttonGroupElement.classList.add("jspsych-btn-group-grid"); if (trial.grid_rows === null && trial.grid_columns === null) { throw new Error( - "You must specify the number of rows or columns when using the grid layout." + "You cannot set `grid_rows` to `null` without providing a value for `grid_columns`." ); } const n_cols = diff --git a/packages/plugin-image-button-response/src/index.ts b/packages/plugin-image-button-response/src/index.ts index d487cb1460..5d910877a5 100644 --- a/packages/plugin-image-button-response/src/index.ts +++ b/packages/plugin-image-button-response/src/index.ts @@ -200,7 +200,7 @@ class ImageButtonResponsePlugin implements JsPsychPlugin { buttonGroupElement.classList.add("jspsych-btn-group-grid"); if (trial.grid_rows === null && trial.grid_columns === null) { throw new Error( - "You must specify the number of rows or columns when using the grid layout." + "You cannot set `grid_rows` to `null` without providing a value for `grid_columns`." ); } const n_cols = diff --git a/packages/plugin-video-button-response/src/index.ts b/packages/plugin-video-button-response/src/index.ts index 5828ee85de..dffa0218f2 100644 --- a/packages/plugin-video-button-response/src/index.ts +++ b/packages/plugin-video-button-response/src/index.ts @@ -198,7 +198,7 @@ class VideoButtonResponsePlugin implements JsPsychPlugin { buttonGroupElement.classList.add("jspsych-btn-group-grid"); if (trial.grid_rows === null && trial.grid_columns === null) { throw new Error( - "You must specify the number of rows or columns when using the grid layout." + "You cannot set `grid_rows` to `null` without providing a value for `grid_columns`." ); } const n_cols = From 66f813f9ca86d4385b25d08e9129fedef0fedf32 Mon Sep 17 00:00:00 2001 From: Josh de Leeuw Date: Wed, 18 Oct 2023 15:37:47 -0400 Subject: [PATCH 07/12] update changeset --- .changeset/button-layouts.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.changeset/button-layouts.md b/.changeset/button-layouts.md index 47ff1df98a..da53781d20 100644 --- a/.changeset/button-layouts.md +++ b/.changeset/button-layouts.md @@ -5,4 +5,6 @@ Button plugins now support either `display: grid` or `display: flex` on the container element that hold the buttons. If the layout is `grid`, the number of rows and/or columns can be specified. +The `margin_horizontal` and `margin_vertical` parameters have been removed from the button plugins. If you need control over the button CSS, you can add inline style to the button element using the `button_html` parameter. + jspsych.css has new layout classes to support this feature. From d7f3040d517680e9aa45908fbc850c05176769e5 Mon Sep 17 00:00:00 2001 From: Josh de Leeuw Date: Wed, 18 Oct 2023 15:45:06 -0400 Subject: [PATCH 08/12] fix copy/paste error of div name --- packages/plugin-audio-button-response/src/index.ts | 2 +- packages/plugin-canvas-button-response/src/index.ts | 2 +- packages/plugin-image-button-response/src/index.ts | 2 +- packages/plugin-video-button-response/src/index.ts | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/plugin-audio-button-response/src/index.ts b/packages/plugin-audio-button-response/src/index.ts index ec71a52437..60c7d8126f 100644 --- a/packages/plugin-audio-button-response/src/index.ts +++ b/packages/plugin-audio-button-response/src/index.ts @@ -154,7 +154,7 @@ class AudioButtonResponsePlugin implements JsPsychPlugin { // Display buttons const buttonGroupElement = document.createElement("div"); - buttonGroupElement.id = "jspsych-html-button-response-btngroup"; + buttonGroupElement.id = "jspsych-audio-button-response-btngroup"; if (trial.button_layout === "grid") { buttonGroupElement.classList.add("jspsych-btn-group-grid"); if (trial.grid_rows === null && trial.grid_columns === null) { diff --git a/packages/plugin-canvas-button-response/src/index.ts b/packages/plugin-canvas-button-response/src/index.ts index a8350250ae..d64171cb17 100644 --- a/packages/plugin-canvas-button-response/src/index.ts +++ b/packages/plugin-canvas-button-response/src/index.ts @@ -114,7 +114,7 @@ class CanvasButtonResponsePlugin implements JsPsychPlugin { // Display buttons const buttonGroupElement = document.createElement("div"); - buttonGroupElement.id = "jspsych-html-button-response-btngroup"; + buttonGroupElement.id = "jspsych-canvas-button-response-btngroup"; if (trial.button_layout === "grid") { buttonGroupElement.classList.add("jspsych-btn-group-grid"); if (trial.grid_rows === null && trial.grid_columns === null) { diff --git a/packages/plugin-image-button-response/src/index.ts b/packages/plugin-image-button-response/src/index.ts index 5d910877a5..0d47b4d872 100644 --- a/packages/plugin-image-button-response/src/index.ts +++ b/packages/plugin-image-button-response/src/index.ts @@ -195,7 +195,7 @@ class ImageButtonResponsePlugin implements JsPsychPlugin { // Display buttons const buttonGroupElement = document.createElement("div"); - buttonGroupElement.id = "jspsych-html-button-response-btngroup"; + buttonGroupElement.id = "jspsych-images-button-response-btngroup"; if (trial.button_layout === "grid") { buttonGroupElement.classList.add("jspsych-btn-group-grid"); if (trial.grid_rows === null && trial.grid_columns === null) { diff --git a/packages/plugin-video-button-response/src/index.ts b/packages/plugin-video-button-response/src/index.ts index dffa0218f2..fbf08ae1e3 100644 --- a/packages/plugin-video-button-response/src/index.ts +++ b/packages/plugin-video-button-response/src/index.ts @@ -193,7 +193,7 @@ class VideoButtonResponsePlugin implements JsPsychPlugin { // Display buttons const buttonGroupElement = document.createElement("div"); - buttonGroupElement.id = "jspsych-html-button-response-btngroup"; + buttonGroupElement.id = "jspsych-video-button-response-btngroup"; if (trial.button_layout === "grid") { buttonGroupElement.classList.add("jspsych-btn-group-grid"); if (trial.grid_rows === null && trial.grid_columns === null) { From 9cabb614e70257038755b3f1a364141b34b7dd72 Mon Sep 17 00:00:00 2001 From: Josh de Leeuw Date: Wed, 18 Oct 2023 15:52:54 -0400 Subject: [PATCH 09/12] update formatting in changeset --- .changeset/button-layouts.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.changeset/button-layouts.md b/.changeset/button-layouts.md index da53781d20..0ba3717c1c 100644 --- a/.changeset/button-layouts.md +++ b/.changeset/button-layouts.md @@ -3,8 +3,6 @@ "jspsych": patch --- -Button plugins now support either `display: grid` or `display: flex` on the container element that hold the buttons. If the layout is `grid`, the number of rows and/or columns can be specified. - -The `margin_horizontal` and `margin_vertical` parameters have been removed from the button plugins. If you need control over the button CSS, you can add inline style to the button element using the `button_html` parameter. +Button plugins now support either `display: grid` or `display: flex` on the container element that hold the buttons. If the layout is `grid`, the number of rows and/or columns can be specified. The `margin_horizontal` and `margin_vertical` parameters have been removed from the button plugins. If you need control over the button CSS, you can add inline style to the button element using the `button_html` parameter. jspsych.css has new layout classes to support this feature. From a99c7b79632e3f96e9de8a296850974130247b18 Mon Sep 17 00:00:00 2001 From: Josh de Leeuw Date: Thu, 19 Oct 2023 09:10:35 -0400 Subject: [PATCH 10/12] fix typo in class name --- packages/plugin-image-button-response/src/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/plugin-image-button-response/src/index.ts b/packages/plugin-image-button-response/src/index.ts index 0d47b4d872..a8a6619710 100644 --- a/packages/plugin-image-button-response/src/index.ts +++ b/packages/plugin-image-button-response/src/index.ts @@ -195,7 +195,7 @@ class ImageButtonResponsePlugin implements JsPsychPlugin { // Display buttons const buttonGroupElement = document.createElement("div"); - buttonGroupElement.id = "jspsych-images-button-response-btngroup"; + buttonGroupElement.id = "jspsych-image-button-response-btngroup"; if (trial.button_layout === "grid") { buttonGroupElement.classList.add("jspsych-btn-group-grid"); if (trial.grid_rows === null && trial.grid_columns === null) { From acce785dd77ecde88878aa9d72683d7195f6c2b3 Mon Sep 17 00:00:00 2001 From: Josh de Leeuw Date: Thu, 19 Oct 2023 09:10:56 -0400 Subject: [PATCH 11/12] manually update snapshots --- packages/plugin-html-button-response/src/index.spec.ts | 2 +- packages/plugin-image-button-response/src/index.spec.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/plugin-html-button-response/src/index.spec.ts b/packages/plugin-html-button-response/src/index.spec.ts index cc9d32a469..76e5018fea 100644 --- a/packages/plugin-html-button-response/src/index.spec.ts +++ b/packages/plugin-html-button-response/src/index.spec.ts @@ -15,7 +15,7 @@ describe("html-button-response", () => { ]); expect(getHTML()).toMatchInlineSnapshot( - '"
this is html
"' + '"
this is html
"' ); }); diff --git a/packages/plugin-image-button-response/src/index.spec.ts b/packages/plugin-image-button-response/src/index.spec.ts index eea6fd8431..e7c274b609 100644 --- a/packages/plugin-image-button-response/src/index.spec.ts +++ b/packages/plugin-image-button-response/src/index.spec.ts @@ -17,7 +17,7 @@ describe("image-button-response", () => { // expect(getHTML()).toContain('
"' + '"
"' ); }); From 45e0d65e7dc3ba3a24ae69a84dc7cbc1d422f725 Mon Sep 17 00:00:00 2001 From: Josh de Leeuw Date: Thu, 19 Oct 2023 09:24:22 -0400 Subject: [PATCH 12/12] update documentation for `button_html` and `button_layout` --- docs/plugins/audio-button-response.md | 7 ++++--- docs/plugins/canvas-button-response.md | 7 ++++--- docs/plugins/html-button-response.md | 7 ++++--- docs/plugins/image-button-response.md | 7 ++++--- docs/plugins/video-button-response.md | 7 ++++--- 5 files changed, 20 insertions(+), 15 deletions(-) diff --git a/docs/plugins/audio-button-response.md b/docs/plugins/audio-button-response.md index a91d7e1195..f20155f40e 100644 --- a/docs/plugins/audio-button-response.md +++ b/docs/plugins/audio-button-response.md @@ -18,11 +18,12 @@ In addition to the [parameters available in all plugins](../overview/plugins.md# | ------------------------------ | ---------------- | ---------------------------------------- | ---------------------------------------- | | stimulus | audio file | *undefined* | Path to audio file to be played. | | choices | array of strings | *undefined* | Labels for the buttons. Each different string in the array will generate a different button. | -| button_html | HTML string | `''` | A template of HTML for generating the button elements. You can override this to create customized buttons of various kinds. The string `%choice%` will be changed to the corresponding element of the `choices` array. You may also specify an array of strings, if you need different HTML to render for each button. If you do specify an array, the `choices` array and this array must have the same length. The HTML from position 0 in the `button_html` array will be used to create the button for element 0 in the `choices` array, and so on. | +| button_html | function | ``(choice: string, choice_index: number)=>```; | A function that generates the HTML for each button in the `choices` array. The function gets the string and index of the item in the `choices` array and should return valid HTML. If you want to use different markup for each button, you can do that by using a conditional on either parameter. The default parameter returns a button element with the text label of the choice. | | prompt | string | null | This string can contain HTML markup. Any content here will be displayed below the stimulus. The intention is that it can be used to provide a reminder about the action the participant is supposed to take (e.g., which key to press). | | trial_duration | numeric | null | How long to wait for the participant to make a response before ending the trial in milliseconds. If the participant fails to make a response before this timer is reached, the participant's response will be recorded as null for the trial and the trial will end. If the value of this parameter is null, the trial will wait for a response indefinitely. | -| margin_vertical | string | '0px' | Vertical margin of the button(s). | -| margin_horizontal | string | '8px' | Horizontal margin of the button(s). | +| button_layout | string | 'grid' | Setting to `'grid'` will make the container element have the CSS property `display: grid` and enable the use of `grid_rows` and `grid_columns`. Setting to `'flex'` will make the container element have the CSS property `display: flex`. You can customize how the buttons are laid out by adding inline CSS in the `button_html` parameter. | +| grid_rows | number | 1 | The number of rows in the button grid. Only applicable when `button_layout` is set to `'grid'`. If null, the number of rows will be determined automatically based on the number of buttons and the number of columns. | +| grid_columns | number | null | The number of columns in the button grid. Only applicable when `button_layout` is set to `'grid'`. If null, the number of columns will be determined automatically based on the number of buttons and the number of rows. | | response_ends_trial | boolean | true | If true, then the trial will end whenever the participant makes a response (assuming they make their response before the cutoff specified by the `trial_duration` parameter). If false, then the trial will continue until the value for `trial_duration` is reached. You can set this parameter to `false` to force the participant to listen to the stimulus for a fixed amount of time, even if they respond before the time is complete. | | trial_ends_after_audio | boolean | false | If true, then the trial will end as soon as the audio file finishes playing. | | response_allowed_while_playing | boolean | true | If true, then responses are allowed while the audio is playing. If false, then the audio must finish playing before the button choices are enabled and a response is accepted. Once the audio has played all the way through, the buttons are enabled and a response is allowed (including while the audio is being re-played via on-screen playback controls). | diff --git a/docs/plugins/canvas-button-response.md b/docs/plugins/canvas-button-response.md index 578b4eaf9f..5d00220fa6 100644 --- a/docs/plugins/canvas-button-response.md +++ b/docs/plugins/canvas-button-response.md @@ -13,12 +13,13 @@ Parameter | Type | Default Value | Description stimulus | function | *undefined* | The function to draw on the canvas. This function automatically takes a canvas element as its only argument, e.g. `function(c) {...}` or `function drawStim(c) {...}`, where `c` refers to the canvas element. Note that the stimulus function will still generally need to set the correct context itself, using a line like `let ctx = c.getContext("2d")`. canvas_size | array | [500, 500] | Array that defines the size of the canvas element in pixels. First value is height, second value is width. choices | array of strings | [] | Labels for the buttons. Each different string in the array will generate a different button. -button_html | HTML string | `''` | A template of HTML for generating the button elements. You can override this to create customized buttons of various kinds. The string `%choice%` will be changed to the corresponding element of the `choices` array. You may also specify an array of strings, if you need different HTML to render for each button. If you do specify an array, the `choices` array and this array must have the same length. The HTML from position 0 in the `button_html` array will be used to create the button for element 0 in the `choices` array, and so on. +button_html | function | ``(choice: string, choice_index: number)=>```; | A function that generates the HTML for each button in the `choices` array. The function gets the string and index of the item in the `choices` array and should return valid HTML. If you want to use different markup for each button, you can do that by using a conditional on either parameter. The default parameter returns a button element with the text label of the choice. prompt | string | null | This string can contain HTML markup. Any content here will be displayed below the stimulus. The intention is that it can be used to provide a reminder about the action the participant is supposed to take (e.g., what question to answer). trial_duration | numeric | null | How long to wait for the participant to make a response before ending the trial in milliseconds. If the participant fails to make a response before this timer is reached, the participant's response will be recorded as null for the trial and the trial will end. If the value of this parameter is null, the trial will wait for a response indefinitely. stimulus_duration | numeric | null | How long to display the stimulus in milliseconds. The visibility CSS property of the stimulus will be set to `hidden` after this time has elapsed. If this is null, then the stimulus will remain visible until the trial ends. -margin_vertical | string | '0px' | Vertical margin of the button(s). -margin_horizontal | string | '8px' | Horizontal margin of the button(s). +button_layout | string | 'grid' | Setting to `'grid'` will make the container element have the CSS property `display: grid` and enable the use of `grid_rows` and `grid_columns`. Setting to `'flex'` will make the container element have the CSS property `display: flex`. You can customize how the buttons are laid out by adding inline CSS in the `button_html` parameter. +grid_rows | number | 1 | The number of rows in the button grid. Only applicable when `button_layout` is set to `'grid'`. If null, the number of rows will be determined automatically based on the number of buttons and the number of columns. +grid_columns | number | null | The number of columns in the button grid. Only applicable when `button_layout` is set to `'grid'`. If null, the number of columns will be determined automatically based on the number of buttons and the number of rows. response_ends_trial | boolean | true | If true, then the trial will end whenever the participant makes a response (assuming they make their response before the cutoff specified by the `trial_duration` parameter). If false, then the trial will continue until the value for `trial_duration` is reached. You can use this parameter to force the participant to view a stimulus for a fixed amount of time, even if they respond before the time is complete. ## Data Generated diff --git a/docs/plugins/html-button-response.md b/docs/plugins/html-button-response.md index 39b237981b..9619c73881 100644 --- a/docs/plugins/html-button-response.md +++ b/docs/plugins/html-button-response.md @@ -12,12 +12,13 @@ Parameter | Type | Default Value | Description ----------|------|---------------|------------ stimulus | HTML string | undefined | The HTML content to be displayed. choices | array of strings | [] | Labels for the buttons. Each different string in the array will generate a different button. -button_html | HTML string | `''` | A template of HTML for generating the button elements. You can override this to create customized buttons of various kinds. The string `%choice%` will be changed to the corresponding element of the `choices` array. You may also specify an array of strings, if you need different HTML to render for each button. If you do specify an array, the `choices` array and this array must have the same length. The HTML from position 0 in the `button_html` array will be used to create the button for element 0 in the `choices` array, and so on. +button_html | function | ``(choice: string, choice_index: number)=>```; | A function that generates the HTML for each button in the `choices` array. The function gets the string and index of the item in the `choices` array and should return valid HTML. If you want to use different markup for each button, you can do that by using a conditional on either parameter. The default parameter returns a button element with the text label of the choice. prompt | string | null | This string can contain HTML markup. Any content here will be displayed below the stimulus. The intention is that it can be used to provide a reminder about the action the participant is supposed to take (e.g., which key to press). trial_duration | numeric | null | How long to wait for the participant to make a response before ending the trial in milliseconds. If the participant fails to make a response before this timer is reached, the participant's response will be recorded as null for the trial and the trial will end. If the value of this parameter is null, the trial will wait for a response indefinitely. stimulus_duration | numeric | null | How long to display the stimulus in milliseconds. The visibility CSS property of the stimulus will be set to `hidden` after this time has elapsed. If this is null, then the stimulus will remain visible until the trial ends. -margin_vertical | string | '0px' | Vertical margin of the button(s). -margin_horizontal | string | '8px' | Horizontal margin of the button(s). +button_layout | string | 'grid' | Setting to `'grid'` will make the container element have the CSS property `display: grid` and enable the use of `grid_rows` and `grid_columns`. Setting to `'flex'` will make the container element have the CSS property `display: flex`. You can customize how the buttons are laid out by adding inline CSS in the `button_html` parameter. +grid_rows | number | 1 | The number of rows in the button grid. Only applicable when `button_layout` is set to `'grid'`. If null, the number of rows will be determined automatically based on the number of buttons and the number of columns. +grid_columns | number | null | The number of columns in the button grid. Only applicable when `button_layout` is set to `'grid'`. If null, the number of columns will be determined automatically based on the number of buttons and the number of rows. response_ends_trial | boolean | true | If true, then the trial will end whenever the participant makes a response (assuming they make their response before the cutoff specified by the `trial_duration` parameter). If false, then the trial will continue until the value for `trial_duration` is reached. You can set this parameter to `false` to force the participant to view a stimulus for a fixed amount of time, even if they respond before the time is complete. ## Data Generated diff --git a/docs/plugins/image-button-response.md b/docs/plugins/image-button-response.md index 198b0f1acc..19c435e0d0 100644 --- a/docs/plugins/image-button-response.md +++ b/docs/plugins/image-button-response.md @@ -17,12 +17,13 @@ stimulus_height | integer | null | Set the height of the image in pixels. If lef stimulus_width | integer | null | Set the width of the image in pixels. If left null (no value specified), then the image will display at its natural width. maintain_aspect_ratio | boolean | true | If setting *only* the width or *only* the height and this parameter is true, then the other dimension will be scaled to maintain the image's aspect ratio. choices | array of strings | [] | Labels for the buttons. Each different string in the array will generate a different button. -button_html | HTML string | `''` | A template of HTML for generating the button elements. You can override this to create customized buttons of various kinds. The string `%choice%` will be changed to the corresponding element of the `choices` array. You may also specify an array of strings, if you need different HTML to render for each button. If you do specify an array, the `choices` array and this array must have the same length. The HTML from position 0 in the `button_html` array will be used to create the button for element 0 in the `choices` array, and so on. +button_html | function | ``(choice: string, choice_index: number)=>```; | A function that generates the HTML for each button in the `choices` array. The function gets the string and index of the item in the `choices` array and should return valid HTML. If you want to use different markup for each button, you can do that by using a conditional on either parameter. The default parameter returns a button element with the text label of the choice. prompt | string | null | This string can contain HTML markup. Any content here will be displayed below the stimulus. The intention is that it can be used to provide a reminder about the action the participant is supposed to take (e.g., which key to press). stimulus_duration | numeric | null | How long to show the stimulus for in milliseconds. If the value is null, then the stimulus will be shown until the participant makes a response. trial_duration | numeric | null | How long to wait for the participant to make a response before ending the trial in milliseconds. If the participant fails to make a response before this timer is reached, the participant's response will be recorded as null for the trial and the trial will end. If the value of this parameter is null, the trial will wait for a response indefinitely. -margin_vertical | string | '0px' | Vertical margin of the button(s). -margin_horizontal | string | '8px' | Horizontal margin of the button(s). +button_layout | string | 'grid' | Setting to `'grid'` will make the container element have the CSS property `display: grid` and enable the use of `grid_rows` and `grid_columns`. Setting to `'flex'` will make the container element have the CSS property `display: flex`. You can customize how the buttons are laid out by adding inline CSS in the `button_html` parameter. +grid_rows | number | 1 | The number of rows in the button grid. Only applicable when `button_layout` is set to `'grid'`. If null, the number of rows will be determined automatically based on the number of buttons and the number of columns. +grid_columns | number | null | The number of columns in the button grid. Only applicable when `button_layout` is set to `'grid'`. If null, the number of columns will be determined automatically based on the number of buttons and the number of rows. response_ends_trial | boolean | true | If true, then the trial will end whenever the participant makes a response (assuming they make their response before the cutoff specified by the `trial_duration` parameter). If false, then the trial will continue until the value for `trial_duration` is reached. You can set this parameter to `false` to force the participant to view a stimulus for a fixed amount of time, even if they respond before the time is complete. render_on_canvas | boolean | true | If true, the image will be drawn onto a canvas element. This prevents a blank screen (white flash) between consecutive image trials in some browsers, like Firefox and Edge. If false, the image will be shown via an img element, as in previous versions of jsPsych. If the stimulus is an **animated gif**, you must set this parameter to false, because the canvas rendering method will only present static images. diff --git a/docs/plugins/video-button-response.md b/docs/plugins/video-button-response.md index 6890031e62..7e7c29802a 100644 --- a/docs/plugins/video-button-response.md +++ b/docs/plugins/video-button-response.md @@ -14,9 +14,10 @@ Parameter | Type | Default Value | Description ----------|------|---------------|------------ stimulus | array | *undefined* | An array of file paths to the video. You can specify multiple formats of the same video (e.g., .mp4, .ogg, .webm) to maximize the [cross-browser compatibility](https://developer.mozilla.org/en-US/docs/Web/HTML/Supported_media_formats). Usually .mp4 is a safe cross-browser option. The plugin does not reliably support .mov files. The player will use the first source file in the array that is compatible with the browser, so specify the files in order of preference. choices | array of strings | *undefined* | Labels for the buttons. Each different string in the array will generate a different button. -button_html | HTML string | `''` | A template of HTML for generating the button elements. You can override this to create customized buttons of various kinds. The string `%choice%` will be changed to the corresponding element of the `choices` array. You may also specify an array of strings, if you need different HTML to render for each button. If you do specify an array, the `choices` array and this array must have the same length. The HTML from position 0 in the `button_html` array will be used to create the button for element 0 in the `choices` array, and so on. -margin_vertical | string | '0px' | Vertical margin of the button(s). -margin_horizontal | string | '8px' | Horizontal margin of the button(s). +button_html | function | ``(choice: string, choice_index: number)=>```; | A function that generates the HTML for each button in the `choices` array. The function gets the string and index of the item in the `choices` array and should return valid HTML. If you want to use different markup for each button, you can do that by using a conditional on either parameter. The default parameter returns a button element with the text label of the choice. +button_layout | string | 'grid' | Setting to `'grid'` will make the container element have the CSS property `display: grid` and enable the use of `grid_rows` and `grid_columns`. Setting to `'flex'` will make the container element have the CSS property `display: flex`. You can customize how the buttons are laid out by adding inline CSS in the `button_html` parameter. +grid_rows | number | 1 | The number of rows in the button grid. Only applicable when `button_layout` is set to `'grid'`. If null, the number of rows will be determined automatically based on the number of buttons and the number of columns. +grid_columns | number | null | The number of columns in the button grid. Only applicable when `button_layout` is set to `'grid'`. If null, the number of columns will be determined automatically based on the number of buttons and the number of rows. prompt | string | null | This string can contain HTML markup. Any content here will be displayed below the stimulus. The intention is that it can be used to provide a reminder about the action the participant is supposed to take (e.g., which key to press). width | numeric | width of the video file | The width of the video display in pixels. height | numeric | heigh of the video file | The height of the video display in pixels.