Search code examples
jqueryqualtrics

Add button to qualtrics question which (randomly) appends text to question


I have a Qualtrics survey where I am showing people a gamble and asking them to decide to play it or not. Prior to that, I want them to virtually play out the gamble like 20 times and see the result of each. It seemed like the easiest way to do this would be to add a button to the question text which, when pressed, randomly appends a new result of the gamble -- either win or lose. E.g. if I am having them play out a gamble with a 90% chance of winning, 90% of the time they press the button they should see a new "WIN" appended to the page, and 10% of the time they should see "LOSE" appended to the page.

However, I'm struggling to get this all working within qualtrics. Individually I have a sense of what I need to be doing, I think -- it seems like if I make a div in the question HTML itself, and then make a button which will use the .append function in JQuery to add either a win or lose message (i.e. .append(<p> WIN! </p>) or something like that), it should give me my basic functionality. But I'm totally lost when it comes to actually implementing this, and figuring out what should go into the html of the question itself vs. the JavaScript section of Qualtrics.

I'd also ideally like to require them to do this 20 times, but how to track that is a bit beyond me. Any help (or advice on better ways to do this) would be very appreciated. I'd really like to avoid having to use the survey flow in Qualtrics, since that seems super messy for this many trials, but if there is a good way to do it like that I'd appreciate suggestions there as well.

Edit: I have an implementation of this which isn't really what I wanted, but gets a similar effect without using JQuery at all.

This is not the JQuery or button-based way to solve this -- I couldn't figure that out. Instead, I created a loop and merge block which consisted of two text displays with a page break between. The first text display would tell them to press the button to simulate a gamble. Javascript on this page would simulate the results of the gamble based on embedded data, and then update another embedded data field for the display of the gamble's outcome, which would be shown on the following block.

The Javascript on the initial text question looked like this, where q1start is an embedded data field which sets the probability of winning the gamble:

Qualtrics.SurveyEngine.addOnReady(function()
{
    /*Place your JavaScript here to run when the page is fully displayed*/
    
    //turn starting probability into a variable
    var start_prob = parseInt("${e://Field/q1start}")
    console.log("next thing is start prob")
    console.log(start_prob)
    
    //draw a number 0-100 to see if we won the lottery
    var random_draw_result = Math.floor(Math.random()*100+1)
    //compare it to chances, set embedded data which will display outcome
    var outcome_display = (start_prob >= random_draw_result) ? "WIN!" : "LOSE!"
    console.log("draw")
    console.log(random_draw_result)
    console.log("outcome")
    console.log(outcome_display)
    Qualtrics.SurveyEngine.setEmbeddedData("outcome_display", outcome_display)

});

The second text question then just looked like:

"Your result was ${e://Field/outcome_display}", where the embedded data is the result of the Javascript above which was done during the first step.

Then I just looped and merged this a bunch, and set it so that for all loops and merges before the final loop those two text questions would appear. For the final loop, I had the actual question I wanted them to answer appear instead.

This is what an example block looks like (in this case I just have it do two example trials and then the final, real trial): enter image description here

And this is what the survey flow looked like: enter image description here

In principle, if I wanted to display the results of all the gambles at once, I think I could do it by creating an outcome display embedded data variable for each loop that I'm going to do, and then having that second question just display all of those outcome display variables each time.


Solution

  • Pretty straightforward in the end, finally figured this out.

    Make a block with a single question with this as the HTML:

    <p>Imagine you are considering a ${lm://Field/1}% gamble. Please simulate this gamble 20 times by pressing the button below</p>
    <button id="gamble_btn">Simulate Gamble</button>
    
    <p>&nbsp;</p>
    
    <div id="results">&nbsp;</div>
    

    For this block, make it a loop and merge with a single field which is the probability of winning each of the gambles. Then, attach the following Javascript to that question:

    Qualtrics.SurveyEngine.addOnReady(function()
    {
        /*Place your JavaScript here to run when the page is fully displayed*/
        
        // Hide the continue button
        $('NextButton').hide();
        
        //Probability of winning the gamble
        var start_prob = parseInt("${lm://Field/1}") // Set this to the value for the loop and merge field
        
        var click_ct = 0 //initial # of trials should be 0
        var max_clicks = 20 //number of trials we want them to do
        var complete_alert = "You have finished all gambles" //alert msg for when they click post finishing all gambles
        var completion_message = "<p>You have finished all gambles! Press continue to move on. </p>" // msg to append when finished
        
        // This button allows you to simulate a gamble
        jQuery( "#gamble_btn" ).click(function() {
            console.log("press")
            // Calculate results of gamble, set display message
            var random_draw_result = Math.floor(Math.random()*100+1)
            var outcome_display = (start_prob >= random_draw_result) ? "<p style='color:green;'> WIN! </p>" : "<p style='color:red;'> LOSE! </p>"
            // If they've done less than 20 gambles, append the outcome
            if (click_ct < max_clicks){ // what to do on trials before the last one
                jQuery("#results").append(outcome_display) //display outcome of the trial
                click_ct++
            } else if (click_ct == max_clicks) { //what to do on last trial
                jQuery("#results").append(outcome_display) //append results of final trial
                jQuery("#results").append(completion_message) //append completion message
                $('NextButton').show(); //show the continue button
                jQuery(this).attr('disabled', true); //disable button presses
                click_ct++
            } else {
                alert(complete_alert)
            }
            console.log(click_ct)
        });
    
    });