Problems converting manually set sliders to psychoJS

OS (e.g. Win10): Windows 7
PsychoPy version (e.g. 1.84.x): 2020.1.3
What are you trying to achieve?: I have a routine that consists of a text response or a slider (radio buttons) whose attributes change each repetition depending on a conditions table. This routine works perfectly in PsychoPy, but does not translate well into PsychoJS when the code is uploaded to Pavlovia and tested in Pilot mode. I’m attaching a simplified version of the routine here.

At least 2 things go wrong that I am able to test so far:

  1. For the text-response portion of the routine, feedback is given as soon as the mouse hovers over the “Accept” button without needing to click it (e.g., if you enter an age less than 18), although in PsychoPy feedback is given only after clicking “Accept”.

  2. I can’t test the sliders because I run into a " TypeError: Cannot convert a Symbol value to a string" error message if I enter a valid age and click Accept. This seems to be coming from an attempt to create the radio-button slider.

core-2020.1.js:1480 TypeError: Cannot convert a Symbol value to a string
at String.indexOf ()
at Slider._applyStyle (visual-2020.1.js:1017)
at Slider._buildSlider (visual-2020.1.js:847)
at Slider._updateIfNeeded (visual-2020.1.js:822)
at Slider.setAutoDraw (core-2020.1.js:2054)
at Scheduler._currentTask (demoqntest.js:366)
at Scheduler._runNextTasks (util-2020.1.js:1093)
at Scheduler._runNextTasks (util-2020.1.js:1096)
at Scheduler._runNextTasks (util-2020.1.js:1096)
at update (util-2020.1.js:1060)
window.onerror @ core-2020.1.js:1480

and line 366 corresponds to " qn_slider.setAutoDraw(true);"

I’d appreciate any insight into these errors!

acceptbtn demographics.xlsx (9.1 KB) demoqntest.psyexp (35.5 KB)

1 Like

I’m not sure you can use $respStyle == “radio”, $respStyle == “text” etc in start conditions

However, you could see what happens if you remove the $

I removed the $ from the start condition (and actually replaced the conditional test with a boolean whose state was set in the code component) and the same error occurred.

I also tried casting the respStyle variable as a string in the visual.slider() function, which didn’t seem to help either.

The latest code changes are uploaded on gitlab: https://gitlab.pavlovia.org/CML-lab/demoqntest

I was able to fix the mouse button press issue by changing the if statement from

if sum(demoqn_mouse.getPressed()) and accept_demo.contains(demoqn_mouse):

to

if demoqn_mouse.getPressed()[0]==1 and accept_demo.contains(demoqn_mouse):

I then went into the JS code and noticed that my manual call to create the slider did not match the syntax of the initialization of the slider code component, so I edited the JS portion of the code component to match. This got me past the first problem but now I’m running into a new one:

TypeError: ratings.map is not a function
at Slider._ratingToPos (visual-2020.1.js:1054)
at Slider._buildSlider (visual-2020.1.js:866)
at Slider._updateIfNeeded (visual-2020.1.js:822)
at Slider.setAutoDraw (core-2020.1.js:2054)
at Scheduler._currentTask (demoqntest.js:372)
at Scheduler._runNextTasks (util-2020.1.js:1093)
at Scheduler._runNextTasks (util-2020.1.js:1096)
at Scheduler._runNextTasks (util-2020.1.js:1096)
at update (util-2020.1.js:1060)

(note, line 372 still points to the same line as before).

.map is not a function suggests to me that you can’t use .contains on a slider. Is accept_demo the slider?

No, that’s the button for the mouse press. .contains isn’t being used in the portion of the code related to the slider initialization call; all I do there is mimic the same JS code that initialized the slider in the first place:

qn_slider = new visual.Slider({win: win, name: 'qn_slider', size: [0.025, slider_height], pos: [0.1, 0], units: 'height', labels: labels, ticks: Number.parseInt(ticks), granularity: 1, style: [visual.Slider.Style.RADIO], color: new util.Color('LightGray'), fontFamily: 'HelveticaBold', bold: true, italic: false, flip: false,labelHeight: 0.04});

This seems to suggest that I can’t manually call visual.slider in a code component?

I figured it out; it turns out that I can’t create a new visual.Slider manually in JS (I can do so in PsychoPy), but I can manually set the existing slider properties depending on my conditions table:

code in PsychoPy:

    qn_slider = visual.Slider(win=win, name='qn_slider',
        size=(0.025, slider_height), pos=(0.1, 0), units='height',
        labels=demolabels, ticks=demoticks,
        granularity=1, style=(respStyle),
        color='LightGray', font='HelveticaBold',
        flip=False, labelHeight = .04)

code in JS (with a slider component also added in the builder):

    qn_slider.size = [0.025, slider_height];
    qn_slider.labels = demolabels;
    qn_slider.ticks = demoticks;
    qn_slider._needVertexUpdate = true;
    qn_slider._buildSlider();
1 Like

Thanks. I found the same with sounds. I’ve added a link to your post from my crib sheet.

1 Like

I’m trying to solve this problem, but haven’t been successful with your solution yet. I am trying to pull in a variable from my conditions file that refreshes the slider labels for each trial. The slider variable will have something like “yes, no” in the csv.

It works on psychopy, not on pavlovia. I essentially want to do this solution How to link loop parameter to slider without 'syntax error' - #2 by dvbridges in pavlovia.

If I just use the JS code you wrote in the right side of a code component, changing only the slider & conditions file names, I get the error that “ratings.map is not a function”.

Coder component:

I have also tried this (attempt at switching around “.join” arguments into what I think is javascript format), and get the same error:
slider_bugv2

I’m on python 2020.1.3, windows10, firefox.

Is that the entirety of the js code needed to adjust the slider, or did you need to make a list of the current demolabels in the code component to pull from?

Hi Sawal,

My solution assumes that you already created the slider using a slider component, and just need to modify the parameters of the slider (I wasn’t able to figure out how to initialize a new slider component purely in JS code).

It turns out that the labels get read in as a single string, so you have to parse the string first. For example:

    demolabels = respOptions.split(",");

Likewise, if you are going to change the ticks, those also need to be parsed, but in addition they need to be converted to numbers.

In psychopy your code would look something like:

    demoticks = respTicks.split(',')
    demoticks = [int(i) for i in demoticks] 

and in PsychoJS, your code would look more complicated:

    demoticks = respTicks.split(",");
    demoticks = function () {
    var _pj_a = [], _pj_b = demoticks;
    for (var _pj_c = 0, _pj_d = _pj_b.length; (_pj_c < _pj_d); _pj_c += 1) {
        var i = _pj_b[_pj_c];
        _pj_a.push(Number.parseInt(i));
    }
    return _pj_a;
}
.call(this);
1 Like

Awong, thank you so much for your prompt reply! I have been trying to figure out how to get a questionnaire on pavlovia that has more functionality, and this works (Psychopy 2020.1.1 as of now)! Fantastic.

If other folks need it, this is the whole JS code together with spacing etc. that can be used to alter your slider on pavlovia, with functionality to pull in question-specific ticks and labels from your Conditions file:

demolabels = qLabs.split(",");
demoticks = qTiks.split(",");
demoticks = function () {
   var _pj_a = [], _pj_b = demoticks;
   for (var _pj_c = 0, _pj_d = _pj_b.length; (_pj_c < _pj_d); _pj_c += 1) {
      var i = _pj_b[_pj_c];
      _pj_a.push(Number.parseInt(i));
   }
   return _pj_a;
}
.call(this);

slider.size = [1.0, 0.1];
slider.labels = demolabels;
slider.ticks = demoticks;
slider._needVertexUpdate = true;
slider._buildSlider();

Where “slider” is the name of your slider, “qLabs” is the name of your labels & “qTiks” is the name of your ticks in Conditions file.

I’ll also not that the two vars from your Conditions file need to be separated with both comma & space like below-- I initially only had comma and the “.split” fx didn’t enjoy that.
condPic

Cheers!