How to dynamically adjust text & numbers below sliders in constant sum question? | XM Community
Solved

How to dynamically adjust text & numbers below sliders in constant sum question?

  • 7 September 2018
  • 13 replies
  • 232 views

Badge +3
Hi everyone,
For a research study, I would like participants to allocate 100 tokens among two recipients. Each token is worth $5.

In a simple version of the question, I managed to have a javascript code, such that when participants entered the token allocations (e.g., 50/50), they would automatically see the implied $ amount ($250/$250).

To make the question more appealing and intuitive, I would like participants to move slider bars indicating the token allocations (instead of entering the desired amounts). While participants adjust the sliders to decide how many tokens to allocate, I would like the text on the screen to also adjust and display the implied $ amount.

Searching online I found this link (https://stackoverflow.com/questions/29538632/in-qualtrics-how-to-dynamically-connect-two-sliders) to add two connected sliders to my question.

I've added it to my question. The problem is that I can't manage to change the javascript code such that, when the participant moves the sliders, the text on the screen also adjusts the implied $ amount.

I have little knowledge of javascript, and would very much appreciate your input. How can I have the question text change as the sliders are moved?

Here is a link to my survey question (code), which combines the code generating the two connected sliders, with my previous code adjusting the text when token amounts were entered directly.

https://drive.google.com/open?id=1SII-1-O_HT_yBNNR-6TvnzmDjMZTzvR4

Thank you very much!
icon

Best answer by Anonymous 11 September 2018, 21:14

View original

13 replies

Hello @Marta ,

The following code will work for "Constant sum" -> "Draggable Bars", with choices= 2.

Paste the following code in the `js(OnReady)` of the Constant sum question.

var that=this.questionId;
var p= Math.round(jQuery("[id='"+that+"~1~track']").width()/100);

jQuery("<p style='width:100%'><span id='currA'>0</span> points for <u>PARTICIPANT A</u> worth 1 cent each. She gets <u><span id='totalA'>0</span></u> cents</p>").insertBefore("tr.First");
jQuery("<p style='width:100%'><span id='currB'>0</span> points for <u>PARTICIPANT B</u> worth 2 cent each. She gets <u><span id='totalB'>0</span></u> cents</p>").insertAfter("tr.First");

jQuery("[id='"+that+"~1~result']").bind('input propertychange',function(){

var A=parseInt(jQuery("[id='"+that+"~1~result']").val());
console.log(A);
jQuery("[id='"+that+"~2~result']").val(100-A);
var t=parseInt(100-A);
jQuery("[id='"+that+"~2~holder']").addClass("activated");
jQuery("[id='"+that+"~2~handle']").css({"left":p*t+"px"});
jQuery("[id='"+that+"~2~bar']").css({"width":p*t+"px"});
var A=parseInt(jQuery("[id='"+that+"~1~result']").val());
jQuery("#currA").text(A);
jQuery("#totalA").text(A*5);
var B=parseInt(jQuery("[id='"+that+"~2~result']").val());
jQuery("#currB").text(B);
jQuery("#totalB").text(B*5);
});

jQuery("[id='"+that+"~2~result']").bind('input propertychange',function(){

var B=parseInt(jQuery("[id='"+that+"~2~result']").val());
console.log(B);
jQuery("[id='"+that+"~1~result']").val(100-B);
var t=parseInt(100-B);
jQuery("[id='"+that+"~1~holder']").addClass("activated");
jQuery("[id='"+that+"~1~handle']").css({"left":p*t+"px"});
jQuery("[id='"+that+"~1~bar']").css({"width":p*t+"px"});
var A=parseInt(jQuery("[id='"+that+"~1~result']").val());
jQuery("#currA").text(A);
jQuery("#totalA").text(A*5);
var B=parseInt(jQuery("[id='"+that+"~2~result']").val());
jQuery("#currB").text(B);
jQuery("#totalB").text(B*5);
});


jQuery(document).on('change', function(){

var A=parseInt(jQuery("[id='"+that+"~1~result']").val());
jQuery("#currA").text(A);
jQuery("#totalA").text(A*5);
var B=parseInt(jQuery("[id='"+that+"~2~result']").val());
jQuery("#currB").text(B);
jQuery("#totalB").text(B*5);
});

Please find the attached QSF file of implementation.
Preview Link
Badge +3
This is extremely helpful. Thank you so much!

I have a question related to the QSF file, which works great.

If I would like to place the two pieces of text ("X points for PARTICIPANT A worth 1 cent each. Shet gets X cents." and "100-X points for PARTICIPANT B worth 2 cent each. She gets (100-X)*2 cents") below the two slider bards, how could I adjust their placement?

I've tried to change insertBefore for insertAfter, but I think I may also need to change "tr.First", tried "tr.Last" and "tr.Second", but that doesn't work.

What would you recommend?

Thank you very much again!
> @Marta said:
> This is extremely helpful. Thank you so much!
>
> I have a question related to the QSF file, which works great.
>
> If I would like to place the two pieces of text ("X points for PARTICIPANT A worth 1 cent each. Shet gets X cents." and "100-X points for PARTICIPANT B worth 2 cent each. She gets (100-X)*2 cents") below the two slider bards, how could I adjust their placement?
>
> I've tried to change insertBefore for insertAfter, but I think I may also need to change "tr.First", tried "tr.Last" and "tr.Second", but that doesn't work.
>
> What would you recommend?
>
> Thank you very much again!

Change the line 3 and 4(the line which contains insert After/Before) to the below code

jQuery("<p id='customid' style='width:100%; margin-bottom:10px'><span id='currA'>0</span> points for <u>PARTICIPANT A</u> worth 1 cent each. She gets <u><span id='totalA'>0</span></u> cents</p>").insertAfter("div.ChoiceStructure");
jQuery("<p style='width:100%'><span id='currB'>0</span> points for <u>PARTICIPANT B</u> worth 2 cent each. She gets <u><span id='totalB'>0</span></u> cents</p>").insertAfter("#customid");
Badge +3
Hi Shashi,
Thanks again for your help. This is really really helpful! My question now looks great.

I have a quick question: How do I set a different "custom start position"? If I would like the sliders to start at 100 for A, and 0 for B, where can I adjust this initial position on the javascript code?

Thanks again!!
Marta
> @Marta said:
> Hi Shashi,
> Thanks again for your help. This is really really helpful! My question now looks great.
>
> I have a quick question: How do I set a different "custom start position"? If I would like the sliders to start at 100 for A, and 0 for B, where can I adjust this initial position on the javascript code?
>
> Thanks again!!
> Marta
>

Drag the slider for A to 100 in the survey tab as shown in the image!

Also change the start text in the JS code accordingly
Badge +3
Thanks again!

I have one, hopefully final question. I am using smaller multipliers, e.g., each token is worth 0.1 or 0.08, and I am having trouble rounding up the numbers. Depending on how I move the bars, many decimals appear (see image).

I tried substituting ParseInt for ParseFloat, and also creating a new variable that would do the operations. Neither change worked.

Would you have a suggestion as to how to fix the JS code?

Thank you!
!
> @Marta said:
> Thanks again!
>
> I have one, hopefully final question. I am using smaller multipliers, e.g., each token is worth 0.1 or 0.08, and I am having trouble rounding up the numbers. Depending on how I move the bars, many decimals appear (see image).
>
> I tried substituting ParseInt for ParseFloat, and also creating a new variable that would do the operations. Neither change worked.
>
> Would you have a suggestion as to how to fix the JS code?
>
> Thank you!
> !
>
>
>
>
>
If you want decimals upto 2 digits, use the below code
`jQuery("#totalB").text((B*0.08).toFixed(2));`


If you don't want decimals, use the below code it will round to next whole numbers i.e 5.88 to 6
`jQuery("#totalB").text(Math.round(B*0.08));`
Badge +3
Hi Shashi,
I have been using your feedback for this question, and it's great. Thank you again.

I now have a question about how qualtrics records the subject's final decision. I have set the initial positions of the bars at 100 for A and 0 for B.

Suppose we label the question q1. Qualtrics stores q1_1 and q1_2 for each bar.

If an individual only changes the upper bar to 53 (for A), I get q1_1=53, and q1_2=0.
If an individual only changes the lower bar to 44 (for B ), I get q1_1=100, and q1_2=44.

However, if she changes both bars in the process of deciding (and clicking next), I get q1_1=53 and q1_2=44. It is impossible that this was her final decision, since the tokens have to add up to 100.

But now I do not know what was her final decision before submitting. Was it q1_1=53 (and then q1_2=47) or q1_1=56 (since q1_2=44)? How can I know?

How should I deal with this? Storing the "final" position submitted would be very helpful (crucial) for my survey.

Thank you very much!
Hello @Marta ,

Follow the below steps to get the correct slider value

Step 1: Create two embedded data(Slider1Value, Slider2Value) before the constant sum question

Step 2: Paste the following code in the js(onReady) of the constant sum question

var that=this.questionId;
jQuery("[id='"+that+"~2~holder']").addClass("activated");
jQuery("[id='"+that+"~1~holder']").addClass("activated");

var p= Math.round(jQuery("[id='"+that+"~1~track']").width()/100);

jQuery("<p id='customid' style='width:100%; margin-bottom:10px'><span id='currA'>0</span> points for <u>PARTICIPANT A</u> worth 1 cent each. She gets <u><span id='totalA'>0</span></u> cents</p>").insertAfter("div.ChoiceStructure");
jQuery("<p style='width:100%'><span id='currB'>0</span> points for <u>PARTICIPANT B</u> worth 2 cent each. She gets <u><span id='totalB'>0</span></u> cents</p>").insertAfter("#customid");

jQuery("[id='"+that+"~1~result']").bind('input propertychange',function(){
//alert("A hua");
var A=parseInt(jQuery("[id='"+that+"~1~result']").val());
console.log(A);
if((A+parseInt(jQuery("[id='"+that+"~2~result']").val()))==100) {
Qualtrics.SurveyEngine.setEmbeddedData( 'Slider1Value', A );
Qualtrics.SurveyEngine.setEmbeddedData( 'Slider2Value',parseInt(jQuery("[id='"+that+"~2~result']").val()));
console.log("rturn");
return;
}
jQuery("[id='"+that+"~2~result']").val(100-A);
var t=parseInt(100-A);
jQuery("[id='"+that+"~2~holder']").addClass("activated");
jQuery("[id='"+that+"~2~handle']").css({"left":p*t+"px"});
jQuery("[id='"+that+"~2~bar']").css({"width":p*t+"px"});
var A=parseInt(jQuery("[id='"+that+"~1~result']").val());
jQuery("#currA").text(A);
jQuery("#totalA").text((A*0.08).toFixed(2));
var B=parseInt(jQuery("[id='"+that+"~2~result']").val());
jQuery("#currB").text(B);
jQuery("#totalB").text((B*0.08).toFixed(2));

});

jQuery("[id='"+that+"~2~result']").bind('input propertychange',function(){
// alert("B hua");
var B=parseInt(jQuery("[id='"+that+"~2~result']").val());
console.log(B);
if((B+parseInt(jQuery("[id='"+that+"~1~result']").val()))==100) {
Qualtrics.SurveyEngine.setEmbeddedData( 'Slider2Value', B);
Qualtrics.SurveyEngine.setEmbeddedData( 'Slider1Value',parseInt(jQuery("[id='"+that+"~1~result']").val()));
console.log("rturn");
return;
}
jQuery("[id='"+that+"~1~result']").val(100-B);
var t=parseInt(100-B);
jQuery("[id='"+that+"~1~holder']").addClass("activated");
jQuery("[id='"+that+"~1~handle']").css({"left":p*t+"px"});
jQuery("[id='"+that+"~1~bar']").css({"width":p*t+"px"});
var A=parseInt(jQuery("[id='"+that+"~1~result']").val());
jQuery("#currA").text(A);
jQuery("#totalA").text((A*0.08).toFixed(2));
var B=parseInt(jQuery("[id='"+that+"~2~result']").val());
jQuery("#currB").text(B);
jQuery("#totalB").text((B*0.08).toFixed(2));

});


jQuery(document).on('change', function(){
//alert("AB");
var A=parseInt(jQuery("[id='"+that+"~1~result']").val());
jQuery("#currA").text(A);
jQuery("#totalA").text((A*0.08).toFixed(2));
var B=parseInt(jQuery("[id='"+that+"~2~result']").val());
jQuery("#currB").text(B);
jQuery("#totalB").text((B*0.08).toFixed(2));



});
Step 3: Use that two embedded data in data and analysis for your reference to know the slider value.
Userlevel 2
Badge +3
I have encountered the same problem as you, the data record is not correct, the first step and the third step of the three steps of shashi are not very clear can tell me in detail, cut a picture and so on, thank you very much!
Badge +3
Hi Cathaya,
I am posting the js below. I'm not sure it is what you wanted exactly, but I think it worked for me.

Here's an image:
!


Here's the code:
Qualtrics.SurveyEngine.addOnReady(function()
{
/*Place your JavaScript here to run when the page is fully displayed*/

var that=this.questionId;
jQuery("[id='"+that+"~2~holder']").addClass("activated");
jQuery("[id='"+that+"~1~holder']").addClass("activated");

var p= Math.round(jQuery("[id='"+that+"~1~track']").width()/100);

jQuery("<p id='customid' style='width:100%; margin-bottom:10px; text-align: center'> \\
<br> <br> <strong>             \\
After worker 1 works TODAY, <br> she/he </strong> keeps <span id='currA'>100</span> tokens, \\
worth $0.10 each. She gets <strong><u>$<span id='totalA'>10</span></u> \\
TODAY.</strong></p>").insertAfter("div.ChoiceStructure");
jQuery("<p style='width:100%; text-align: center'> \\
<br> <strong>             \\
After worker 2 works IN 1 MONTH, <br> she/he </strong> gets <span id='currB'>0</span> tokens, \\
worth $0.08 each. She gets <strong><u>$<span id='totalB'>0</span></u> \\
in 1 MONTH.</strong></p>").insertAfter("#customid");

jQuery("[id='"+that+"~1~result']").bind('input propertychange',function(){

var A=parseFloat(jQuery("[id='"+that+"~1~result']").val());
console.log(A);
if((A+parseInt(jQuery("[id='"+that+"~2~result']").val()))==100) {
Qualtrics.SurveyEngine.setEmbeddedData( 'SliderValue1_1', A );
Qualtrics.SurveyEngine.setEmbeddedData( 'SliderValue1_2',parseInt(jQuery("[id='"+that+"~2~result']").val()));
console.log("rturn");
return;
}

jQuery("[id='"+that+"~2~result']").val(100-A);
var t=parseFloat(100-A);
jQuery("[id='"+that+"~2~holder']").addClass("activated");
jQuery("[id='"+that+"~2~handle']").css({"left":p*t+"px"});
jQuery("[id='"+that+"~2~bar']").css({"width":p*t+"px"});
var A=parseFloat(jQuery("[id='"+that+"~1~result']").val());
jQuery("#currA").text(A);
jQuery("#totalA").text((A*0.1).toFixed(2));
var B=parseFloat(jQuery("[id='"+that+"~2~result']").val());
jQuery("#currB").text(B);
jQuery("#totalB").text((B*0.08).toFixed(2));

});

jQuery("[id='"+that+"~2~result']").bind('input propertychange',function(){

var B=parseFloat(jQuery("[id='"+that+"~2~result']").val());
console.log(B);
if((B+parseInt(jQuery("[id='"+that+"~1~result']").val()))==100) {
Qualtrics.SurveyEngine.setEmbeddedData( 'SliderValue1_2', B);
Qualtrics.SurveyEngine.setEmbeddedData( 'SliderValue1_1',parseInt(jQuery("[id='"+that+"~1~result']").val()));
console.log("rturn");
return;
}


jQuery("[id='"+that+"~1~result']").val(100-B);
var t=parseFloat(100-B);
jQuery("[id='"+that+"~1~holder']").addClass("activated");
jQuery("[id='"+that+"~1~handle']").css({"left":p*t+"px"});
jQuery("[id='"+that+"~1~bar']").css({"width":p*t+"px"});
var A=parseFloat(jQuery("[id='"+that+"~1~result']").val());
jQuery("#currA").text(A);
jQuery("#totalA").text((A*0.1).toFixed(2));
var B=parseFloat(jQuery("[id='"+that+"~2~result']").val());
jQuery("#currB").text(B);
jQuery("#totalB").text((B*0.08).toFixed(2));




});


jQuery(document).on('change', function(){

var A=parseFloat(jQuery("[id='"+that+"~1~result']").val());
jQuery("#currA").text(A);
jQuery("#totalA").text((A*0.1).toFixed(2));
var B=parseFloat(jQuery("[id='"+that+"~2~result']").val());
jQuery("#currB").text(B);
jQuery("#totalB").text((B*0.08).toFixed(2));



});



});
Userlevel 2
Badge +3
thanks!
Badge +2

Thanks a lot, it is all extremely helpful!
However, I still see the issue of the final value recording. If a participant keeps selecting different values for each of the two bars, the final data is not recorded correctly. Did any of you find a solution? thanks!

Leave a Reply