1

I'm trying to code an experiment with several 'survey-Likert' trials in which an image is presented above the radio buttons using the 'survey-likert' jspsych plugin. I managed to get this to work but all the images/questions appear on the same page. I would like each to appear on a new page. Ideally with a 'continue' button after each question.

Any help would be much appreciated. Saoirse

Someone suggested that I use a for loop to loop through the images but what I've done so far doesn't work and produces some errors. I'm pretty new to programming and jspsych and haven't been able to figure out why it's not working.


var images = [
        './img/1.png',
    './img/2.png',
        './img/3.png',
    './img/4.png',
        './img/5.png',
    './img/6.png'
 ];


var scale_1 = [
  "Extremely Unlikely", 
  "Unlikely", 
  "Slightly Unlikely", 
  "Slightly Likely", 
  "Likely",
  "Extremely Likely"
];

for (var i = 0; i < images; i++) {
var likert = {
  type: 'survey-likert',
  questions: ['First prompt', 'Second prompt', 'Third prompt', 'Fourth prompt', 'Fifth prompt', 'Sixth prompt'],
  labels: [scale_1, scale_1, scale_1, scale_1, scale_1, scale_1],
  timeline: [
    images[i],
],
 };
}
timeline.push(likert)

I expect that each of my 6 images will appear on a separate page with the radio buttons underneath it. When an option is selected the next image and response option set appears until all 6 have been presented.

This is the error I get:

Uncaught TypeError: Cannot read property 'info' of undefined
    at setDefaultValues (jspsych.js:874)
    at doTrial (jspsych.js:809)
    at nextTrial (jspsych.js:794)
    at Object.window.jsPsych.core.finishTrial (jspsych.js:258)
    at end_trial (jspsych-html-button-response.js:180)
    at after_response (jspsych-html-button-response.js:159)
    at HTMLDivElement.<anonymous> (jspsych-html-button-response.js:128)

And the jsPsych.init() function:

      jsPsych.init({
        timeline: timeline,
        preload_images: images,
        on_finish: function() {
          endExperiment( jsPsych.data.get().csv(), function() { document.write('<div id="endscreen" class="endscreen" style="width:1000px"><div class="endscreen" style="text-align:center; border:0px solid; padding:10px; font-size:120%; width:800px; float:right"><p><br><br><br>All done!<br><br>Your completion code is <span id="turkcode" style="font-weight:bold;font-size:130%">' + turkcode + '</span>. To receive payment for the HIT, return to the Amazon Mechanical Turk page and enter this code. Please contact us if something goes wrong and we\'ll fix it as quickly as possible.</p></div></div>') })
        }
      });
    }

Below is the code I wrote which works except that questions all appear on the same page:

var scale_1 = [
  "Extremely Unlikely", 
  "Unlikely", 
  "Slightly Unlikely", 
  "Slightly Likely", 
  "Likely",
  "Extremely Likely"
];

var likert_page = {
  type: 'survey-likert',
  questions: [
    {prompt: '<img src="img/'+r[0]+'.png"/>', name: 'Obs1', labels: scale_1},
    {prompt: '<img src="img/'+r[1]+'.png"/>', name: 'Obs2', labels: scale_1},
    {prompt: '<img src="img/'+r[2]+'.png"/>', name: 'Obs3', labels: scale_1},
    {prompt: '<img src="img/'+r[3]+'.png"/>', name: 'Obs4', labels: scale_1},
    {prompt: '<img src="img/'+r[4]+'.png"/>', name: 'Obs4', labels: scale_1},
    {prompt: '<img src="img/'+r[5]+'.png"/>', name: 'Obs4', labels: scale_1}
  ],
  randomize_question_order: true
};
timeline.push(likert_page);
Con Des
  • 359
  • 1
  • 2
  • 9
  • can you share jsPsych.init function ? – Casper Oct 10 '19 at 01:29
  • 1
    Two small errors: 1. `timeline.push(likert)` is after the for loop, not at its end. 2. in the for loop's condition, you need `i < images.length` –  Oct 10 '19 at 01:30
  • 1
    @Casper Of course, just shared it above! – Con Des Oct 10 '19 at 01:57
  • 1
    @ChrisG Thanks for pointing that out. I've changed the loop's condition. Do you mean the ```timeline.push(likert)``` should look like this ```}; timeline.push(likert)```. Apologies for my ignorance I'm pretty new to this! – Con Des Oct 10 '19 at 01:59
  • I guess; you need to run that line right after setting the `var likert`, before closing the loop with another `}`. –  Oct 10 '19 at 02:19
  • @ConDes I assume you have already defined this **timeline** and Chris G is correct you need to push elements to **timeline** array inside the for loop – Casper Oct 10 '19 at 02:32
  • 1
    @Casper Yes, just moved it inside the loop but that didn't work either. I haven't defined the timeline except for inside the loop. Can you explain what you mean in more detail? – Con Des Oct 10 '19 at 02:38
  • @ConDes I tried this is this what you want ? https://jsbin.com/xajixodiqi/edit?html,console,output – Casper Oct 10 '19 at 03:23
  • 1
    @Casper Thanks for giving it ago but not quite what I was trying to do. I've posted some code above which does what I want without the loop and without showing each question on a separate page. – Con Des Oct 10 '19 at 03:40
  • Please check this https://jsbin.com/xajixodiqi/1/edit?html,console,output – Casper Oct 10 '19 at 04:06

1 Answers1

2

Try to pass questions like below if you do not want to use for loop,

 var scale_1 = [
       "Extremely Unlikely", 
       "Unlikely", 
       "Slightly Unlikely"
    ]; 

   var trial_1 = {
        type: "survey-likert",
        questions: [
        {
          prompt: '<img src="https://b.thumbs.redditmedia.com/wrt8Y0ISSnLljlERAyBQwA6jsoI2WqJPd8sxn7iT-gY.png"/>', name: 'Obs1', labels: scale_1
        }, 
      ]
   }

   var trial_2 = {
     type: 'survey-likert',
     questions: [
       {
         prompt: '<img src="https://cdn141.picsart.com/308218064033201.jpg?c256x256"/>', name: 'Obs2', labels: scale_1
       }, 
     ]
   }

  var trial_3 = {
    type: 'survey-likert',
    questions: [
      {
        prompt: '<img src="https://upload.wikimedia.org/wikipedia/commons/c/c3/Aurora_as_seen_by_IMAGE.PNG"/>', name: 'Obs3', labels: scale_1
      }, 
    ]
  }   

  jsPsych.init({
     timeline: [trial_1, trial_2, trial_3]
  });

Working sample: https://jsbin.com/losebenere/edit?html,js,output

Using for loop you can simplify,

var images = [
  "https://b.thumbs.redditmedia.com/wrt8Y0ISSnLljlERAyBQwA6jsoI2WqJPd8sxn7iT-gY.png",
  "https://cdn141.picsart.com/308218064033201.jpg?c256x256",
  "https://upload.wikimedia.org/wikipedia/commons/c/c3/Aurora_as_seen_by_IMAGE.PNG"
]

var scale_1 = [
  "Extremely Unlikely", 
  "Unlikely", 
  "Slightly Unlikely"
]

for (var i = 0; i < images.length; i++) {
  timeline.push({
    type: "survey-likert",
    questions: [{
        prompt: "<img src=" + images[i]+ ">", name: 'Obs' + i, labels: scale_1
      }
    ]
  });
}

jsPsych.init({
  timeline: timeline
});

Working sample: https://jsbin.com/hedukecawo/edit?html,js,console,output

Casper
  • 1,469
  • 10
  • 19
  • 1
    this works, thank you so much! I now understand what you mean about pushing the timeline elements inside the loop. Thanks again! – Con Des Oct 10 '19 at 05:15