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 - #7 by awong26). 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();

Hello @sawal,

I am very glad that we are progressing!

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).

This is not what I am observing on my end. Do you have code that I could look at? I suspect that you may not have considered the color you gave to the slider. For example, the following code does produce a slider with violet labels and tick and a magenta marker, as intended:

slider = new visual.Slider({
    ...
    style: [visual.Slider.Style.RATING],
    color: new util.Color([(- 0.498), (- 1.0), (- 0.498)]), 
  });
slider._skin.STANDARD.MARKER_COLOR = new util.Color([1, -1, 1]);

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.

Yes, this is the intended behaviour. The skin approach makes it possible to change the style of a given slider, without affecting all sliders. In other words, you can customize your sliders however you see fit.

It is possible for you to customize all of your sliders by changing the properties of Slider.Skin. Once again, this is early days and I will make it possible to do so in a more elegant way. But, already, you can try the following:

visual.Slider.Skin.STANDARD.MARKER_COLOR = new util.Color([-1, 0.004, 1]);

This will change the marker color for all sliders, without your needing to change each slider’s _skin.

Incidentally, both approaches can be combined: you can update the generic style by changing the properties of Slider.Skin and you can update a specific slider’s style by changing its _skin.

Alain

Hi @apitiot,

Thank you for following up! I just tested the first issue again (slider marker, slider, and label colors all changing to specified col when slider is type rating) without making changes, and got the error “rgb is undefined”. Looking back at the slider, somehow the color in the Appearance tab was “$None”-- not sure how that happened since I never changed it to none.
Anyway once I gave that a color, it behaves as you said. Previously I used a light blue color to make sure I knew what I was controlling vs default color settings and the whole thing changed to light blue-- so who knows, maybe it overwrote the accidental $None and is no longer doing that, fine by me!

For the second issue mentioned, what I’m seeing is that using:

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

on the first slider in a routine changes the slider marker for the current routine, but will also change the slider marker color for the following sliders in subsequent routines. So it seems like at least for slider._skin.WHITE_ON_BLACK, it’s actually behaving like slider.Skin.WHITE_ON_BLACK. If I add another slider._skin.WHITE_ON_BLACK to a subsequent slider it changes appropriately, but if I don’t, that second slider marker will use the color from the previous slider marker.

That is wonderful to have a more general approach, I feel like I’m using so much repeat code to all sliders maintain many of the same characteristics (but need to be in different routines due to positioning, sizes, random/sequential orders, etc.).

Testing:
visual.Slider.Skin.STANDARD.MARKER_COLOR: works as expected-- writing this once a code component for the first slider maintains the specified marker color for the remaining sliders-- great!
visual.Slider.Skin.MARKER_SIZE:
– does not work for rating sliders (doesn’t change marker size, but also no errors).
– does work for radio sliders. The code is in the routine that contains a rating slider (which it doesn’t affect), but it changes the size of a later radio slider. However, I’m realizing now that slider._skin.MARKER_SIZE actually doesn’t work for slider type radio (the size does not change), but visual.Slider.skin does.

qn_slider1._skin.MARKER_SIZE = [0.05, 0.05]; 

This is the radio slider size (and this is the same as if I don’t have any radio slider marker size customisation):
image

visual.Slider.Skin.MARKER_SIZE = [0.05, 0.05]; 

Now this is the radio slider size:
image

Again, these are all things I can work around but letting you know what I’ve tested. If you’d prefer to test with a pre-made example I can send it to you.

Thanks Alain!

Hi all, just chiming in to say that the slider code using:

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

Works for me and replaces the old, now defunct method:

slider._needVertexUpdate = true;
slider._buildSlider();

Mainly replying to tag @wakecarter to update the crib sheet (page 13 right above “Translations that require manual editing”) with the correct info or a link to this thread.

1 Like

Thanks. Updated on both crib sheets.

1 Like

Hi @cukelarter, I was unable to get this method to work. What should the slider component in the builder look like (e.g., should the ticks and labels be empty?).