Complex changes in html for each trial (image and dynamic parameter)


I’m sorry - this is a complicated one! :smiley:
I’ve tried to explain the problem as good as I can, but I’m happy to answer any questions! :slight_smile:
And needless to say: I’m extremely grateful for any advice! Dearly needed! :smiley:

I’m working on my first experiment using JsPsych (version 7.2.3) and Pavlovia. The experiment is supposed to display a card in each trial that displays a trial-specific picture, a question about the picture with 2 answer choices (only 1 can be submitted), and a button that opens a modal that provides extra information to answer the question (see image). This information is calculated in the background as it changes based on the participant’s performance in the experiment so far.
What is a good way to do this?

My solution so far:
I worked with the html-survey-form plugin. I’ve ‘cut’ the html that creates the card with the trial specific content into 3 parts, one before the image src is entered, one from after the image src until the information bit is entered, and the last one from here until the end. (like the code below - removed style for readability).

var stim_html_1 = "
        <div >
            <div class='card'>
              <h2'>Does this image show x?</h2>
                <p>Please decide whether the image contains x by selecting one checkbox below.</p>
                <p>You can use the information to the right.</p>
              <div class='parent'>
                <div class='child' ></div>
                <img src="

      var stim_html_2 = "
      <div class='child' ></div>
          <div class='child' >
            <p><strong>Further Information:</strong></p>
            <button type='button' class='btn' id='ModPred'>View Information</button>
                <div id='PopUpModal' class='modal'>
                  <div class='modal-content'>
                    <span class='close'>&times;</span>
                    <p>Information: </p>

      var stim_html_3 = "
                <div class='parent'>
                  <label class='container'>Yes
                    <input type='radio' id='Yes' name='radio' value='YES'>
                    <span class='checkmark'></span>
                  <label class='container' >No
                    <input type='radio' id='No' name='radio' value='NO'>
                    <span class='checkmark'></span>

Then, I created the function “trial_html” to generate an array that has the key-value pairs of “html: ‘html string for the specific trial, with image and model prediction inserted from a table in the background’”. I kind of oriented myself on the jspsych tutorial here. The function looks like this:

// create an empty array to store the dynamic stimulus bits  
        const array_with_each_trial = [];   

 /* creating function that generates array with key-value pairs - key always html, value the html string to display the trial-specific html, including the image and prediction of the trial */
        var trial_html = function () {
          // iterating over length of table (how many entries)
          for (let i = 0; i < table_stimuli.rows.length-1; i++) {              
            // fetch the source of an image (column 1)
            var image_source = "img/" + table_stimuli.columns['image_name'].rows[i+1].innerHTML;   
            // fetch the source of an image (column 2)       
            var image_prediction = table_stimuli.columns['model_prediction'].rows[i+1].innerHTML;       
            // stick them together to a single html string
            array_with_each_trial[i] = stim_html_1.concat(image_source, stim_html_2, image_prediction, stim_html_3);         
          // now the array needs key-value pairs with 'html' always being the key
          function setKey(item, index) {
            var htmlKeyPair = {"html": item};
            return htmlKeyPair;

My trial code looks like this so far:

var trial = {
        type: jsPsychSurveyHtmlForm,
        html: jsPsych.timelineVariable('html'),
        // need to test actual output, not sure because 'response' as stored is actually {"radio":"YES"}
        data: {
            task: 'response',
            correct_answer: jsPsych.timelineVariable('correct_answer')
        on_finish: function(data){
                data.correct = jsPsych.pluginAPI.compareKeys(data.response, data.correct_answer);
              button_label: 'SUBMIT',

Ok, so here are my questions:

  • Not sure whether a function that creates an entire array in every trial makes sense (array cannot be reused in next trial since the ‘additional information’ will change dynamically during the experiment). Does anyone have a better idea?
  • Would a different plugin make more sense? I need to store the selected button and whether the modal was opened.
  • Where would I call this function?
  • I also need to store the correct answer of each trial. I could add another key:value pair to the array that contains correct_response: ‘Yes / No’. Does this seem sensible?

Sorry for the rant!
I hope this explanation made something like sense, let me know if not!
Thank you very much to everyone trying to understand it!


Hi Emma, I think you’ll need help from the jsPsych gurus, whereas this site is more for the PsychoPy/JS users. Try asking the question at Discussions · jspsych/jsPsych · GitHub