psychopy.org | Reference | Downloads | Github

Psychopy 2020.2.2: Did we lose "Slider" code component fx: slider._buildSlider();?

Description of the problem: “Slider” in Psychopy 2020.2.2 update-- using code component in JS to manipulate some of the visuals (eg., labels, number of ticks).
When trying to pilot in Pavlovia, I get the error “slider._buildSlider();” is not a function".

Psychopy2020.2.2, win10, firefox

This has worked for folks on prior psychopy versions (e.g. Problems converting manually set sliders to psychoJS). I just tested it on 2020.1.1, and do not get this error.

This is a simplified version of my current JS code :

qn_slider.labels = ["up", "down"];  // or whatever labels you want
qn_slider._needVertexUpdate = true;
qn_slider._buildSlider();

“qn_slider” is the name of my slider. After updating to py2020.2.2 & attempting to run this, I get the error:
TypeError: qn_slider._buildSlider is not a function

Did we lose “slider._buildSlider()” for JS in the newest update, or should I check something else?

Thank you!

Hello @sawal,

I have made substantial changes to Slider for version 2020.2 (I am polishing the code and documentation and will push them onto GitHub this week but the library itself is of course already available online).

_buildSlider was a protected (i.e. internal) method, which was not meant to be called from the outside, and it is indeed gone. And so is _needVertexUpdate, as a matter of fact.

I understand of course that people were using those as a workaround. If you’d like to share your experiment with me, I can check whether it works without the previous hack, and provide you with an alternative workaround, should it not.
Cheers,

Alain

Hi Alain, It’s still in beta but here’s the URL: https://gitlab.pavlovia.org/Smwalters/tiquestionnaireshttps://pavlovia.org/Smwalters/tiquestionnaires

The slider is a bit limited on customization only using builder interface. Some of the things I’m customizing are ideally slider size/color & label height (can be stable across trials), and pulling labels & ticks from the conditions file that are specific to each question which refreshes for each routine. At the moment it looks like, to do this in pavlovia via JS in 2020.1.1, we need to have a slider component & code component with customization in the same loop, and which is then refreshed each routine & build via I’m assuming _needVertexUpdate & _buildSlider().

Here is the JS code so far that uses slider._buildSlider() in Begin Routine-- haven’t added labelHeight or slider color/size yet. qLabs & qTiks are my labels and ticks vars in 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();

Any suggestions for workarounds using 2020.2.2?

Thank you!

1 Like

Hi @apitiot, are there any updates on possible workarounds for this in 2020.2.2? I’d like to incorporate these code-customized sliders into another exp I designed on this version and am wondering if that’s possible at this point?

Any ideas are appreciated!

Hello @sawal,

My apologies for the delay in getting back to you, it’s been a rather hectic few weeks!

As a matter of fact, you do not need to change _needVertexUpdate (which does not exist any longer) or call _buildSlider (which is also gone) when you want to change the labels or ticks: slider.setLabels() and slider.setTicks() should do it for you.

In terms of fine visual customisation, you could use protected members to change the following:

  • _barFillColor
  • _barLineColor
  • _markerColor
  • _tickColor

and, of course, fontSize, but this one is accessible normally, e.g. slider.setFontSize().

The equivalent of your previous work-around would be to change the attributes above and then do the following:

slider._onChange(true)();
slider._setupSlider()

Please note that those are really hacks, and may stop working in the future. But it should stay in place for a good while.
Let me know how you get on!

Alain

Hi @apitiot, that did the trick! Thank you so much, this works just as expected. I’m sure the psychopy team has been incredibly busy the last few weeks given the surge in users, so I appreciate your taking the time to provide these suggestions.

Now I’m just having trouble changing the marker color and size. I know color in js is different than py–
Begin Experiment:

col = new util.Color([-1, 0, -1]); 

Begin Routine:

qn_slider1._markerColor = col;
qn_slider1._markerSize = (.1,.1);

qn_slider1._onChange(true)();
qn_slider1._setupSlider();

The the marker color/size doesn’t change (and I also don’t get any errors). Has the method to set slider marker color changed? I know in the past it’s been tough for folks to change slider marker size successfully-- can that be done in a more direct way now (as attempted above)?

Thank you!

Hi @apitiot, I’m wondering if you have an update on how changing marker color/size is done in js now given v2020.2.2+? It seems that it’s different than slider._markerColor/ slider._markerSize?

Hello @sawal,

I have now introduced the concept of skin in order to have finer control over the slider’s appearance.
This is rather experimental so do not hesitate to let me know if there are any issues on your end. I will be generalising it in the coming weeks.

All you have to do is to change the parameters of the skin for your marker, which you can do in the following manner:

qn_slider1._skin.WHITE_ON_BLACK.MARKER_COLOR = new util.Color([1, 0, -1]); qn_slider1._skin.MARKER_SIZE = [0.1, 0.1];

Note that you have to specify WHITE_ON_BLACK for the marker’s color if your marker’s style is white on black, otherwise you have to use STANDARD.
Incidentally, (.1,.1) is not valid JavaScript, you have to use: [0.1, 0.1].

Alain

Hi @apitiot,

Thanks for your response!

qn_slider1._skin.MARKER_SIZE = [0.1, 0.1]; works as expected. The slider size changes to specified size, and it only effects the specific slider being called.

The marker color sort of works.
Leaving the slider as type “rating” & using js code: qn_slider1._skin.STANDARD.MARKER_COLOR = new util.Color([1, 0, -1]);
Result: The slider marker color changes, but so does the slider and slider labels.
It only affects the specific slider being called (as expected).

Changing the slider to type “radio” & using js code: qn_slider1._skin.STANDARD.MARKER_COLOR = new util.Color([1, 0, -1]);
Result: Only the slider marker changes to specified color, the slider & labels are unchanged (as expected).

Changing the slider to type “white on black”, and then using js code:
qn_slider1._skin.WHITE_ON_BLACK.MARKER_COLOR = new util.Color([1, 0, -1]);
Result: Only the slider marker changes to specified color, the slider & labels are unchanged (as expected).
However, the slider marker continues to be that color for the following sliders that do not have this code to change marker color for their specific markers. If I add this code to the second slider (using that slider’s name), it does change successfully (and maintains that color for following sliders). This makes me think it’s making a change to a slider property that isn’t then automatically updated for later sliders. Easy to work around on my end, but letting you know.

I haven’t tested this in local version, but are these parameters specific to js or are they available in py too (with corrected syntax)?

Thank you so much Alain!

For others, here’s the final js code in Begin Routine (make sure your slider is type “white on black” in this case). Nothing is needed in other tabs of the code.

qn_slider1.size = [1.0, 0.1];
labs = "no, yes";
q1Labs = labs.split(",");
qn_slider1.setFontSize(.03);
qn_slider1.setLabels(q1Labs);
qn_slider1._skin.MARKER_SIZE = [0.05, 0.05]; 
qn_slider1._skin.WHITE_ON_BLACK.MARKER_COLOR = new util.Color([-1, 0.004, 1]); 

qn_slider1._onChange(true)();
qn_slider1._setupSlider();