skip to Main Content

Background:

Hi all, new to javascript and trying to build a psychological experiment using the tools from the jsPsych (v7.0) library. I built most of what I needed but I’m having a hell of a hard time getting branching logic or conditional filtering to work.

Specifically, I need participants to consent or not consent to study procedures. If they do not consent, they need to be branched to see one message and if they do consent, they need to see another.

I’ve generated a simplified version for replication (See Below)

Issue

I initially thought indexing the value generated by the consent event would be the easiest solution, but I cannot seem to index or reference data from a previous trial. Almost every time, the value that I index appears as [object Object], even though, when I export the data object and look at the thing I think I’m indexing, the ‘0’ value that I expect to see from consenting is there. The code included below is my latest attempt in which I simply try to store the value from the last trial within the response column using the var consented = jsPsych.data.get().last(1).select('response') command. Why isn’t this working? My script as I have it below never meets the conditional statement consented == '0' and always outputs the branch under else.

I’d be open to other branching solutions besides indexing the value of a previous trial if anyone has any.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">

  <!-- Experiment Title -->
  <title>Experiment</title>

  <!-- Loading in libraries  -->
    <script src="https://unpkg.com/[email protected]"></script>
    <script src="https://unpkg.com/@jspsych/[email protected]"></script>
    <script src="https://unpkg.com/@jspsych/[email protected]"></script>
    <link href="https://unpkg.com/[email protected]/css/jspsych.css" rel="stylesheet" type="text/css" />   
</head>

<!-- Determing general page style parameters -->
<body style="background-color: rgb(200, 200, 200);">
<script>

    // Initiating jsPsych
    var jsPsych = initJsPsych();
  
    // Creating an empty array which will act as our timeline
    var timeline = [];

    // | - - - - - Consent - - - - - -|
    // Giving a simple consent event, in which participants select one of two buttons (values corresponding to '0' and '1'. from left to right)
    var consent = {
      type: jsPsychHtmlButtonResponse,
      stimulus: 'Consent Information',
      choices: ['I consent to participanting<br>in this study', 
                'I do not consent to participating<br>in this study'],
      render_on_canvas:false,
      data: {task: 'Consent'},
    }

    // Adding the consent event to the timeline 
    timeline.push(consent);
  
    // (Theoretically) saving the output value of the consent event to a variable named 'consented' 
    var consented = jsPsych.data.get().last(1).select('response')

    // I used  this as a means of viewing the consent output value to check if the previous argument worked. This has always output [object Oject] and I don't know if I'm indexing wrong or I can't view the value of an index in this way, or something about indexing in this way corrupts the value. 
    // var test = {
    //     type: jsPsychHtmlKeyboardResponse,
    //     stimulus: consented,
    //     choices: [' '],
    //     data: {task: 'Instruction'},
    //   };
    //   timeline.push(test);

  // If the participant consents ...
  if (consented == '0'){

    // ... then show this message below.
    var instr_Consented = {
      type: jsPsychHtmlKeyboardResponse,
      stimulus: 'You consented!',
      choices: [' '],
      data: {task: 'Instruction'},
    };
    timeline.push(instr_Consented);
    }
  
  // ... but if the person doesn't consent...
  else {

    // ... show this message instead. 
    var instr_Consented = {
      type: jsPsychHtmlKeyboardResponse,
      stimulus: 'You did not consent!',
      choices: [' '],
      data: {task: 'Instruction'},
    };
    timeline.push(instr_Consented);
  }   

    // Executing the timeline
    jsPsych.run(timeline);

</script>
</body>
</html>

2

Answers


  1. Chosen as BEST ANSWER

    @Josh 's answer appears to work for me, but I just wanted to note an alternative that I figured out before I saw their response:

        // Asking people whether they consent to study participation
        var consent = {
          type: jsPsychImageButtonResponse,
                stimulus: 'Consent Information',
          choices: ['I consent to participanting<br>in this study', 
                    'I do not consent to participating<br>in this study'],
          data: {task: 'Consent'},
          on_finish: function (data) {
    
            // Check the participant's response, if it's the second option
            if (data.response == 1) {
        
              // ... end the experiment
              jsPsych.endExperiment('You did not consent!');
            }
          }
        }
    
        // Adding the consent event to the timeline 
        timeline.push(consent);
      
        // Otherwise, continue as normal
        var instr_Consented = {
          type: jsPsychHtmlKeyboardResponse,
          stimulus: 'You consented!',
          choices: [' '],
          data: {task: 'Instruction'},
        };
        timeline.push(instr_Consented);
        }
     
    

    I swore I tried this before posting the question and it didn't work, but it appears to work now. All I'm doing is adding a funtion to the on_finish condition that ends the experiment and displays a message if they do not consent. Again, the thing I really struggled with was indexing or calling the value and it seems like data.response works just fine here.


  2. The example code doesn’t work because the experiment hasn’t been run yet when you get to the if(consented == 0) conditional, so consented doesn’t reflect the actual response of the subject. jsPsych.run() is called after the timeline is built.

    You can use a conditional timeline to achieve this instead.

    const consented_timeline = {
        timeline: [instr_Consented],
        conditional_function: () => {
            var consented = jsPsych.data.get().last(1).select('response')
            return consented == '0'
        }
    }
    
    const not_consented_timeline = {
        timeline: [instr_NotConsented],
        conditional_function: () => {
            var consented = jsPsych.data.get().last(1).select('response')
            return consented != '0'
        }
    }
    
    timeline.push(consented_timeline, not_consented_timeline);
    

    You may want to modify how the consented variable is retrieved from the data, since .last(1) is not quite as robust in this case (e.g., the second conditional timeline may be checked after the first has already run, so the last trial would not be the consent trial anymore). I’d recommend using .filter() to select the specific consent trial.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search