Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

conditional follow up questions when the main question "YES" is selected. #3233

Open
NanChen5353 opened this issue Feb 14, 2024 · 3 comments

Comments

@NanChen5353
Copy link

NanChen5353 commented Feb 14, 2024

I have been trying to set up a questionnaire full of questions working like this:
for each question, the follow up question is displayed when yes is selected.

But right now, the code I have only works: each main question is on a seperate page, and only after answering all the questions, the follow up questions is showed. (i.e. Question 1, Question 2, follow up question for Q1; follow up question for Q2). just wondering if anyone have a idea how can I modify it to make at least the follow up question is on the same page with its question and ideally, all questions are on the same page? ) Thanks in advance.

Screenshot 2024-02-14 at 12 01 20
var jsPsych = initJsPsych();

var timeline = [];
var caps_qn = [
  '1) Do you ever notice that sounds are much louder than they normally would be?',
  '2) Do you ever sense the presence of another being, despite being unable to see any evidence?',
  // '3) Do you ever hear your own thoughts repeated or echoed?',
  // '4) Do you ever see shapes, lights, or colors even though there is nothing really there?',
  // '5) Do you ever experience unusual burning sensations or other strange feelings in or on your body?',
  // '6) Do you ever hear noises or sounds when there is nothing about to explain them?',
  //     '7) Do you ever hear your own thoughts spoken aloud in your head, so that someone near might be able to hear them?',
  //     '8) Do you ever detect smells which don’t seem to come from your surroundings?',
  //     '9) Do you ever have the sensation that your body, or a part of it, is changing or has changed shape?',
  //     '10) Do you ever have the sensation that your limbs might not be your own or might not be properly connected to your body?',
  //     '11) Do you ever hear voices commenting on what you are thinking or doing?',
  //     '12) Do you ever feel that someone is touching you, but when you look nobody is there?',
  //     '13) Do you ever hear voices saying words or sentences when there is no-one around that might account for it?',
  //     '14) Do you ever experience unexplained tastes in your mouth?',
  //     '15) Do you ever find that sensations happen all at once and flood you with information?',
  //     '16) Do you ever find that sounds are distorted in strange or unusual ways?',
  //     '17) Do you ever have difficulty distinguishing one sensation from another?',
  //     '18) Do you ever smell everyday odors and think that they are unusually strong?',
  //     '19) Do you ever find the appearance of things or people seems to change in a puzzling way, e.g., distorted shapes or sizes or color?',
  //     '20) Do you ever find that your skin is more sensitive to touch, heat, or cold than usual?',
  //     '21) Do you ever think that food or drink tastes much stronger than it normally would?',
  //     '22) Do you ever look in the mirror and think that your face seems different from usual?',
  //     '23) Do you ever have days where lights or colors seem brighter or more intense than usual?',
  //     '24) Do you ever have the feeling of being uplifted, as if driving or rolling over a road while sitting quietly?',
  //     '25) Do you ever find that common smells sometimes seem unusually different?',
  //     '26) Do you ever think that everyday things look abnormal to you?',
  //     '27) Do you ever find that your experience of time changes dramatically?',
  //     '28) Have you ever heard two or more unexplained voices talking with each other?',
  //     '29) Do you ever notice smells or odors that people next to you seem unaware of?',
  //     '30) Do you ever notice that food or drink seems to have an unusual taste?',
  //     '31) Do you ever see things that other people cannot?',
  //     '32) Do you ever hear sounds or music that people near you don’t hear?'
];

// try

function createFollowUpLikert(questionName) {
  return {
    type: jsPsychSurveyLikert,
    questions: [
      { prompt: "Not at all distressing to Very distressing", name: questionName + 'Distressing', labels: ["1", "2", "3", "4", "5"], required: true },
      { prompt: "Not at all distracting to Completely intrusive", name: questionName + 'Distracting', labels: ["1", "2", "3", "4", "5"], required: true },
      { prompt: "Happens hardly at all to Happens all the time", name: questionName + 'Frequency', labels: ["1", "2", "3", "4", "5"], required: true }
    ]
  };
}

function createMainQuestionTrial(questionText, index) {
  var questionName = 'Q' + (index + 1);
  return {
    type: jsPsychSurveyMultiChoice,
    questions: [{ prompt: questionText, options: ['NO', 'YES'], required: true, name: questionName }],
    on_finish: function(data) {
      if(data.response[questionName] === 'YES') {
        // If the response is YES, add the follow-up Likert scale questions to the timeline
        jsPsych.addNodeToEndOfTimeline(createFollowUpLikert(questionName));
      }
    }
  };
}

// Adding each main question trial to the timeline
caps_qn.forEach(function(questionText, index) {
  timeline.push(createMainQuestionTrial(questionText, index));
});

// Start the experiment
jsPsych.run(timeline);
@Shaobin-Jiang
Copy link
Contributor

Each trial is bound to be displayed on a separate page, and you are adding the questions and follow-up questions by inserting multiple trials. The correct way would be to display the questions in one multi-choice trial and use on_load to control the addition of follow-up questions.

The solution is given below. You might want to take a closer look at the comments to better understand it and for further customization.

The javascript code:

let jsPsych = initJsPsych();

let timeline = [];

let caps_qn = [
  '1) Do you ever notice that sounds are much louder than they normally would be?',
  '2) Do you ever sense the presence of another being, despite being unable to see any evidence?',
];

// Add the follow up using multi-choice instead of likert
// After all, the latter can be regarded as a special multi-choice question.
//
// The prefix indicates the name of the question it follows up.
//
// Note though, we are prefixing the name with "follow-up". We are using this name to identify the follow-up querstions
// later.
//
// We are also making the choices display horizontally so that it resembles the real likert survey more.
function create_follow_up_question(prefix) {
    let options = [1, 2, 3, 4, 5];

    let create_name = (name) => `follow-up-${prefix}-${name}`;

    return [
        { prompt: "Not at all distressing to Very distressing", name: create_name('Distressing'), options, horizontal: true },
        { prompt: "Not at all distracting to Completely intrusive", name: create_name('Distracting'), options, horizontal: true  },
        { prompt: "Happens hardly at all to Happens all the time", name: create_name('Frequency'), options, horizontal: true  }
    ]
}

let trial = {
    type: jsPsychSurveyMultiChoice,
    questions: caps_qn.map(function (value, index) {
        return [
            {
                prompt: value,
                required: true,
                name: `Q${index}`,
                options: ['yes', 'no'],
            },
            create_follow_up_question(`Q${index}`),
        ];
    // flat the array as it looks like this prior to flattening:
    //
    // [
    //     [{Q0}, [{follow-up-Q0-Distressing, follow-up-Q0-Distracting}]],
    //     [{Q1}, [{follow-up-Q1-Distressing, follow-up-Q1-Distracting}]],
    // ]
    //
    // Which is why we have to apply a depth=2 flattening
    }).flat(2),
    // custom css_classes
    // go check out the css code now before proceeding
    css_classes: ['survey'],
    on_load: function () {
        // selects the wrapper div of questions whose name begins with Q, i.e., the non-follow-up questions
        for (let elem of document.querySelectorAll('.jspsych-survey-multi-choice-question[data-name^="Q"]')) {
            // the radio elements are the child nodes of the wrapper div
            let radios = elem.querySelectorAll('input');
            for (let radio of radios) {
                // listens to click event on the individual radio elements
                // if the radio element's value is "yes", show the follow up questions; otherwise, hide them
                radio.addEventListener('click', function (event) {
                    let show_follow_up = event.target.value === 'yes';

                    // The name is stored in the data-name property of the wrapper div
                    let name = elem.dataset.name;

                    // We will be using next-sibling combinator to select the wrapper divs of the follow-up questions
                    // This is a base of the selector
                    let selector = `.jspsych-survey-multi-choice-question[data-name^="${name}"]`;

                    for (let i = 0; i < 3; i++) {
                        // Move the selector one element further
                        selector += ' + .jspsych-survey-multi-choice-question';
                        let follow_up = document.querySelector(selector);

                        follow_up.style.display = show_follow_up ? 'block' : 'none';

                        // Do not forget to set the follow-up question as required
                        follow_up.querySelectorAll('input').forEach(function (elem) {
                            elem.required = show_follow_up;
                        })
                    }
                });
            }
        }
    },
}

jsPsych.run([trial]);

The CSS code:

/* The .survey is defined in the javascript code by `css_classes` */
.survey .jspsych-survey-multi-choice-text {
    text-align: left !important;
}

/*
 * Remember back when we created the follow-up questions, where we prefixed
 * each name with a follow-up? We are now selecting these follow-questions and
 * hiding them at the beginning stage.
 */
.survey .jspsych-survey-multi-choice-question[data-name^="follow-up"] {
    display: none;
}

@NanChen5353
Copy link
Author

Thank you very much. really appreciate it! just wondering how do we decide when to use multi-choice, when to use likert then?

@Shaobin-Jiang
Copy link
Contributor

I choose to use multi-choice here because, with the addition of the follow-up question, the trial does not consist only of likert items. A yes-or-no question would be troublesome should we try to implement it in a likert trial. If you never need to make much modification to the plugin and require only likert items, use likert.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants