2

I ask the same matrix table (multiple answer) question twice in my Qualtrics survey. When I display the question to the user the second time, I want the answers to be auto populated from the first time the user answered the question. I've looked at the code snippets in the documentation, so I know how to select the checkboxes in the current question, e.g.

for (var i = 1; i <= rows; i++) {
    for (var j = 1; j <= cols; j++) {
        this.setChoiceValue(i, j, true);
    }
}

My issue is that I can't figure out how to get the selected answers from the previous question. I have tried something like this but it doesn't work (cannot read property 'attr' of null):

var isChecked = $("#QR~QID2~" + i + "~" + j").attr('checked');

This page from the documentation suggests using piped text, something along the lines of:

var selectedChoice = "${q://QID2/ChoiceGroup/SelectedChoices}";

This seems to give me the unique statements in the rows of the survey that have been selected, but I need to get the selected answer (col) for each statement (row) in the question. I'm not sure how to formulate the correct piped text.

Any advice would be much appreciated! Thanks.

Edit 1: Here is the code I ended up using.

Qualtrics.SurveyEngine.addOnload(function()
{
    /*Place Your Javascript Below This Line*/
    var numChecks = $(this.getQuestionContainer()).select('input[type="checkbox"]');
    var numCols = 4;
    var numRows = numChecks.length / numCols;
    var map = {};

    //I won't have more than 20 rows in the matrix
    map[1] = "${q://QID53/SelectedAnswerRecode/1}";
    map[2] = "${q://QID53/SelectedAnswerRecode/2}";
    map[3] = "${q://QID53/SelectedAnswerRecode/3}";
    map[4] = "${q://QID53/SelectedAnswerRecode/4}";
    map[5] = "${q://QID53/SelectedAnswerRecode/5}";
    map[6] = "${q://QID53/SelectedAnswerRecode/6}";
    map[7] = "${q://QID53/SelectedAnswerRecode/7}";
    map[8] = "${q://QID53/SelectedAnswerRecode/8}";
    map[9] = "${q://QID53/SelectedAnswerRecode/9}";
    map[10] = "${q://QID53/SelectedAnswerRecode/10}";
    map[11] = "${q://QID53/SelectedAnswerRecode/11}";
    map[12] = "${q://QID53/SelectedAnswerRecode/12}";
    map[13] = "${q://QID53/SelectedAnswerRecode/13}";
    map[14] = "${q://QID53/SelectedAnswerRecode/14}";
    map[15] = "${q://QID53/SelectedAnswerRecode/15}";
    map[16] = "${q://QID53/SelectedAnswerRecode/16}";
    map[17] = "${q://QID53/SelectedAnswerRecode/17}";
    map[18] = "${q://QID53/SelectedAnswerRecode/18}";
    map[19] = "${q://QID53/SelectedAnswerRecode/19}";
    map[20] = "${q://QID53/SelectedAnswerRecode/20}";


    for (var i = 1; i <= numRows; i++) {
        //Get the recode values for row i
        var rowValues = map[i].split(",");
        //Loop through all the recode values for the current row
        for (var c = 0 ; c < rowValues.length; c++) {
            var val = parseInt(rowValues[c].trim());
            //Select the current question's checkboxes corresponding to the recode values
            this.setChoiceValue(i, val, true);
        }
    }
});

Edit 2:

I'm getting some strange behavior now. I'm trying to populate a table with only 3 rows, so I would think that

    "${q://QID53/SelectedAnswerRecode/1}";
    "${q://QID53/SelectedAnswerRecode/2}";
    "${q://QID53/SelectedAnswerRecode/3}";

would give me the values for the first three rows from the previous table for question "QID53" . But actually those return empty strings, and it's not until calling

    "${q://QID53/SelectedAnswerRecode/5}";
    "${q://QID53/SelectedAnswerRecode/6}";
    "${q://QID53/SelectedAnswerRecode/7}";

that I get the first three values.

For a table of 14 rows, nothing returns until calling

"${q://QID53/SelectedAnswerRecode/4}";

and it leaves the last 3 rows in the table empty.

Am I wrong in assuming that the number after "SelectedAnswerRecode" is the row number? Is there something about an offset that I'm missing?

kulaus
  • 23
  • 5

1 Answers1

1

I think you'll want to pipe in the recode values. Something like:

var r1ar = parseInt("${q://QID2/SelectedAnswerRecode/1}");
var r2ar = parseInt("${q://QID2/SelectedAnswerRecode/2}");

Then set the values:

this.setChoiceValue(1, r1ar, true);
this.setChoiceValue(2, r2ar, true);

Make sure your recode values match the column ids.

Edits/additions based on comments below:

  1. Piped values in the javascript get resolved server side before the page is sent to the browser, so they are fixed values. There is no way to make them dynamic in javascript. If your question has a variable number of rows due to display logic or carryover, you'll have to include all the possible piped values in the javascript, then check them to see which ones are valid.

  2. For a multiple answer matrix, you can convert the comma separated list into an array using str.split(',') then loop through the array. Qualtrics includes spaces after the commas in comma separated lists, so you'll have to trim() the strings in the array.

T. Gibbons
  • 4,919
  • 2
  • 15
  • 32
  • Thanks much! One wrinkle in this is that the number of rows in my matrix table will vary depending on the survey, so it would be great to be able to programatically generate the piped text, e.g. `var r = parseInt("${q://QID2/SelectedAnswerRecode/" + i + "}");` but that doesn't seem to work as described here:[http://stackoverflow.com/questions/25849755/using-operators-within-a-string-qualtrics-javascript] – kulaus Jan 27 '16 at 16:39
  • Also I'd add that since I'm using a multiple answer matrix table, `"${q://QID2/SelectedAnswerRecode/1}"` will return a comma-separated string of the values selected for row 1. – kulaus Jan 27 '16 at 16:47
  • one possible way to help with making the code reusable would be to set each value as part of one associative array rather than as separate variables. then you could write the second half of the script to perform the setChoiceValue for each key/value pair in the array. you will still have to manually code each variable to capture, but it would minimize the amount of code necessary. I'll try and post up a basic implementation of this a bit later! – Anthony Rivas Jan 27 '16 at 20:54
  • That sounds similar to what I ended up doing, Anthony. I'll post the code I ended up using. – kulaus Jan 28 '16 at 12:31
  • I added some error behaviors in my original question. Would appreciate if anyone could take a look. – kulaus Jan 28 '16 at 18:24
  • As you've found out, they aren't necessarily the row numbers. This can happen for two reasons (1) If you've edited your choices (for example if you have an existing question with four choices, and you replace them by going to the first choice and pasting, then your first row will become 5.) (2) If you are using choice display logic, the choices keep their numbering (e.g. if 1 is not displayed, but 2 is, the first populated answer will be for 2). This was what I was thinking when I said that if you have a variable number of rows you'll have to check to see which ones are valid. – T. Gibbons Jan 28 '16 at 18:54
  • One additional reason(reason for starting at 4 in particular is if you copy paste a list into qualtrics for some reason it defaults the first answer to 4 instead of 1. – Anthony Rivas Jan 29 '16 at 16:21
  • Yep, I had been pasting in the row values (for both questions) from a .csv file. I ended up having to check for valid rows in each of the questions. Thanks so much for the help. – kulaus Jan 29 '16 at 20:04