In this blog post, I will demonstrate a more advanced use of the DistributionBuilder: keeping track of the participants' allocation process. In a few lines of code, we will get better insights in how the participants are constructing their distributions.
A typical use of DistributionBuilder
A distribution builder is generally used like this:
- Add it to a survey
- Let the participant provides her allocation
- Recover the allocation.
// 1. Create the DistributionBuilder
var distbuilder = new DistributionBuilder()
distbuilder.render("container")
distbuilder.labelize()
// 2. Participants interacting
// Add 3 balls there, remove 2 here, 1 more over here...
// 3. Recover the allocation
console.log(distbuilder.distribution)
But what if you want to know what happened in step 2? What if you want to keep track of all the intermediary steps between the empty distribution builder, and the final allocation provided by participants?
Monitoring the changes in the allocation
The DistributionBuilder library provides a very useful property: onChange. Any function that
you supply to this onChange will be called every time the distribution
changes.
function iHaveChanged() {
// This function just says "I have changed!"
alert("I have changed!")
}
var distbuilder = new DistributionBuilder({"onChange":iHaveChanged})
distbuilder.render("container")
distbuilder.labelize()
The distribution builder now outputs "I have changed!" every time the user makes a change to the allocation.
This is not very useful, but it shows how we can use the onChange property to trigger specific actions when the
participants are changing their allocation of balls.
Recovering and storing the intermediary allocations
Now let's create a better function that will recover the current allocation from the distribution builder, and stores it in an array.
var hist = [] // Empty array that will store the history.
function updateHistory(distbuilder) {
// This function takes a a DistributionBuilder object as argument
var allocation = distbuilder.getDistribution().slice() // Make a copy of the current allocation
hist.push(allocation) // Push this copy to the history array.
}
var distbuilder = new DistributionBuilder({"onChange":() => updateHistory(distbuilder)})
// See below for an explanation on this pattern
distbuilder.render("container")
distbuilder.labelize()
Now this is more useful! Every time a respondent interacts with the distribution builder, the resulting allocation will
be stored in the history array.
A few notes on the code above in case you want to better understand what's going on:
- Unlike in the previous example, we did not bind
updateHistorytoonChange. Instead, we bind a wrapper function that callsupdateHistorywith the objectdistbuilderalready supplied as argument. This is what() => updateHistory(distbuilder)means. - The function
updateHistorymakes a copy (withslice()) of the allocation before pushing it to the array. If you do not make a copy, the content ofhistorywill change every time the allocation changes, and this array will contain X copies of the current allocation instead of the history. If you have the newest version of the library (v1.1), you can omit theslice().
In the example below, you can observe the previous allocations that have been stored.
See the Pen DistBuilderHistory by Quentin Andre (@QuentinAndre) on CodePen.
Store the allocation in Qualtrics
Qualtrics' embedded data fields only accept strings. To store the history in Qualtrics, you will therefore have to convert this array of allocations into one large string.
function historyToString(arr) {
return arr.map(x => x.join(",")).join("*")
}
Qualtrics.SurveyEngine.setEmbdeddedData("HistoryOfAllocations", historyToString(hist))
The function above separates the values within each allocation by commas ',' and the different allocations within the
history by stars '*'.
Now you are all set! You can observe how participants construct their distributions, and get better insights into their thinking process. In the next post, I will discuss results obtained from this paradigm.