applying querySelector to display_element

This commit is contained in:
crava2199 2024-11-25 16:50:14 +01:00
parent df65ce0967
commit afe9ebcc66
3 changed files with 74 additions and 56 deletions

View File

@ -0,0 +1,5 @@
---
"@jspsych/plugin-survey-multi-choice": minor
---
Fixed document form selection

View File

@ -1,5 +1,6 @@
import { clickTarget, simulateTimeline, startTimeline } from "@jspsych/test-utils";
import { initJsPsych } from "jspsych";
import surveyMultiChoice from ".";
jest.useFakeTimers();
@ -10,6 +11,36 @@ const getInputElement = (choiceId: number, value: string) =>
) as HTMLInputElement;
describe("survey-multi-choice plugin", () => {
test("properly ends when has sibling form", async () => {
const container = document.createElement('div')
const outerForm = document.createElement('form')
outerForm.id = 'outer_form'
container.appendChild(outerForm)
const innerDiv = document.createElement('div')
innerDiv.id = 'target_id';
container.appendChild(innerDiv);
document.body.appendChild(container)
const jsPsychInst = initJsPsych({ display_element: innerDiv })
const options = ["a", "b", "c"];
const { getData, expectFinished } = await startTimeline([
{
type: surveyMultiChoice,
questions: [
{ prompt: "Q0", options },
{ prompt: "Q1", options },
]
},
], jsPsychInst);
getInputElement(0, "a").checked = true;
await clickTarget(document.querySelector("#jspsych-survey-multi-choice-next"));
await expectFinished();
})
test("data are logged with the right question when randomize order is true", async () => {
var scale = ["a", "b", "c", "d", "e"];
const { getData, expectFinished } = await startTimeline([
@ -45,7 +76,7 @@ describe("survey-multi-choice plugin", () => {
});
});
describe("survey-likert plugin simulation", () => {
describe("survey-multi-choice plugin simulation", () => {
test("data-only mode works", async () => {
const scale = ["a", "b", "c", "d", "e"];
const { getData, expectFinished } = await simulateTimeline([

View File

@ -109,6 +109,8 @@ const info = <const>{
type Info = typeof info;
const plugin_id_name = "jspsych-survey-multi-choice";
/**
* **survey-multi-choice**
*
@ -124,36 +126,35 @@ class SurveyMultiChoicePlugin implements JsPsychPlugin<Info> {
trial(display_element: HTMLElement, trial: TrialType<Info>) {
const plugin_id_name = "jspsych-survey-multi-choice";
const trial_form_id = `${plugin_id_name}_form`;
var html = "";
// inject CSS for trial
html += '<style id="jspsych-survey-multi-choice-css">';
html +=
".jspsych-survey-multi-choice-question { margin-top: 2em; margin-bottom: 2em; text-align: left; }" +
".jspsych-survey-multi-choice-text span.required {color: darkred;}" +
".jspsych-survey-multi-choice-horizontal .jspsych-survey-multi-choice-text { text-align: center;}" +
".jspsych-survey-multi-choice-option { line-height: 2; }" +
".jspsych-survey-multi-choice-horizontal .jspsych-survey-multi-choice-option { display: inline-block; margin-left: 1em; margin-right: 1em; vertical-align: top;}" +
"label.jspsych-survey-multi-choice-text input[type='radio'] {margin-right: 1em;}";
html += "</style>";
html += `
<style id="${plugin_id_name}-css">
.${plugin_id_name}-question { margin-top: 2em; margin-bottom: 2em; text-align: left; }
.${plugin_id_name}-text span.required {color: darkred;}
.${plugin_id_name}-horizontal .${plugin_id_name}-text { text-align: center;}
.${plugin_id_name}-option { line-height: 2; }
.${plugin_id_name}-horizontal .${plugin_id_name}-option { display: inline-block; margin-left: 1em; margin-right: 1em; vertical-align: top;}
label.${plugin_id_name}-text input[type='radio'] {margin-right: 1em;}
</style>`;
// show preamble text
if (trial.preamble !== null) {
html +=
'<div id="jspsych-survey-multi-choice-preamble" class="jspsych-survey-multi-choice-preamble">' +
trial.preamble +
"</div>";
html += `<div id="${plugin_id_name}-preamble" class="${plugin_id_name}-preamble">${trial.preamble}</div>`;
}
// form element
if (trial.autocomplete) {
html += `<form id="${trial_form_id}">`;
} else {
html += `<form id="${trial_form_id}" autocomplete="off">`;
html += `---------
<form id="${trial_form_id}" autocomplete="off">
---------`;
}
// generate question order. this is randomized here as opposed to randomizing the order of trial.questions
// so that the data are always associated with the same question regardless of order
var question_order = [];
@ -171,22 +172,15 @@ class SurveyMultiChoicePlugin implements JsPsychPlugin<Info> {
var question_id = question_order[i];
// create question container
var question_classes = ["jspsych-survey-multi-choice-question"];
var question_classes = [`${plugin_id_name}-question`];
if (question.horizontal) {
question_classes.push("jspsych-survey-multi-choice-horizontal");
question_classes.push(`${plugin_id_name}-horizontal`);
}
html +=
'<div id="jspsych-survey-multi-choice-' +
question_id +
'" class="' +
question_classes.join(" ") +
'" data-name="' +
question.name +
'">';
html += `<div id="${plugin_id_name}-${question_id}" class="${question_classes.join(" ")}" data-name="${question.name}">`;
// add question text
html += '<p class="jspsych-survey-multi-choice-text survey-multi-choice">' + question.prompt;
html += `<p class="${plugin_id_name}-text survey-multi-choice">${question.prompt}`;
if (question.required) {
html += "<span class='required'>*</span>";
}
@ -195,47 +189,35 @@ class SurveyMultiChoicePlugin implements JsPsychPlugin<Info> {
// create option radio buttons
for (var j = 0; j < question.options.length; j++) {
// add label and question text
var option_id_name = "jspsych-survey-multi-choice-option-" + question_id + "-" + j;
var input_name = "jspsych-survey-multi-choice-response-" + question_id;
var input_id = "jspsych-survey-multi-choice-response-" + question_id + "-" + j;
var option_id_name = `${plugin_id_name}-option-${question_id}-${j}`;
var input_name = `${plugin_id_name}-response-${question_id}`;
var input_id = `${plugin_id_name}-response-${question_id}-${j}`;
var required_attr = question.required ? "required" : "";
// add radio button container
html += '<div id="' + option_id_name + '" class="jspsych-survey-multi-choice-option">';
html += '<label class="jspsych-survey-multi-choice-text" for="' + input_id + '">';
html +=
'<input type="radio" name="' +
input_name +
'" id="' +
input_id +
'" value="' +
question.options[j] +
'" ' +
required_attr +
"></input>";
html += question.options[j] + "</label>";
html += "</div>";
html += `
<div id="${option_id_name}" class="${plugin_id_name}-option">
<label class="${plugin_id_name}-text" for="${input_id}">
<input type="radio" name="${input_name}" id="${input_id}" value="${question.options[j]}" ${required_attr} />
${question.options[j]}
</label>
</div>`;
}
html += "</div>";
}
// add submit button
html +=
'<input type="submit" id="' +
plugin_id_name +
'-next" class="' +
plugin_id_name +
' jspsych-btn"' +
(trial.button_label ? ' value="' + trial.button_label + '"' : "") +
"></input>";
html += `<input type="submit" id="${plugin_id_name}-next" class="${plugin_id_name} jspsych-btn"${trial.button_label ? ' value="' + trial.button_label + '"' : ""} />`;
html += "</form>";
// render
display_element.innerHTML = html;
document.querySelector(`form#${trial_form_id}`).addEventListener("submit", (event) => {
const trial_form = display_element.querySelector<HTMLFormElement>(`#${trial_form_id}`);
trial_form.addEventListener("submit", (event) => {
event.preventDefault();
// measure response time
var endTime = performance.now();
@ -244,7 +226,7 @@ class SurveyMultiChoicePlugin implements JsPsychPlugin<Info> {
// create object to hold responses
var question_data = {};
for (var i = 0; i < trial.questions.length; i++) {
var match = display_element.querySelector("#jspsych-survey-multi-choice-" + i);
var match = display_element.querySelector(`#${plugin_id_name}-${i}`);
var id = "Q" + i;
var val: String;
if (match.querySelector("input[type=radio]:checked") !== null) {
@ -332,7 +314,7 @@ class SurveyMultiChoicePlugin implements JsPsychPlugin<Info> {
for (let i = 0; i < answers.length; i++) {
this.jsPsych.pluginAPI.clickTarget(
display_element.querySelector(
`#jspsych-survey-multi-choice-response-${i}-${trial.questions[i].options.indexOf(
`#${plugin_id_name}-response-${i}-${trial.questions[i].options.indexOf(
answers[i][1]
)}`
),
@ -341,7 +323,7 @@ class SurveyMultiChoicePlugin implements JsPsychPlugin<Info> {
}
this.jsPsych.pluginAPI.clickTarget(
display_element.querySelector("#jspsych-survey-multi-choice-next"),
display_element.querySelector(`#${plugin_id_name}-next`),
data.rt
);
}