Have an idea?

Visit Sawtooth Software Feedback to share your ideas on how we can improve our products.

Drill-down select questions

I have two select questions and I want the value of the second question to dynamically populate based on the answer to the first question. I suppose I could do this on multiple pages, skipping people around to different sections based on their first answer, but I really want to do it all one one page. In fact, I want the second part to be revealed after you answer the first question.

Let's assume my first question is automobile make, as in Ford, Chevrolet, and Toyota. And my second question is the make's model. So if I selected Ford, I would then see Econoline, Expedition, Explorer, and Fiesta. If I selected Chevy, I would see Avalanche, Blazer, Silverado, and Suburban. If I selected Toyota, I would see 4Runner, Highlander, Sequoia, and
Tundra.

I assume you need some custom HTML, jQuery, and CSS to make this happen, but I'm genuinely clueless. Any help?
asked Feb 6, 2017 by JKincaid Bronze (1,035 points)

1 Answer

0 votes
Here's the code from the last time I did drilldowns:

<script>
var dependencyOrder = ['SelectQ1', 'SelectQ2'];
var dependencies = {
    'SelectQ1': {
        1: [1, 2, 3], // if SelectQ1=1, then SelectQ2 will permit responses 1, 2, and 3
        2: [4, 5, 6], // if SelectQ1=2, then SelectQ2 will permit responses 4, 5, and 6
        3: [7, 8, 9] // if SelectQ1=3, then SelectQ2 will permit responses 7, 8, and 9
    }
}

$(document).ready(function(){
    updateDependentDropdowns();
    $('select').change(updateDependentDropdowns);
})

function updateDependentDropdowns() {
    var lastName = dependencyOrder[0];
    var lastVal = Number($('#' + lastName).val());
    for (var thisNum = 1; thisNum < dependencyOrder.length; thisNum++) {
        var thisName = dependencyOrder[thisNum];
        var thisVal = Number($('#' + thisName).val());
        
        if (lastVal == 0) {
            $('#' + thisName).val(0);
            thisVal = 0;
            $('#' + thisName + '_div').hide();
        }
        else {
            $('#' + thisName + '_div').show();
            var thisDependentVals = dependencies[lastName][lastVal];
            if (thisDependentVals.indexOf(thisVal) == -1) {
                $('#' + thisName).val(0);
                thisVal = 0;
            }
            $('#' + thisName + ' option').hide();
            $('#' + thisName + ' option[value=""]').show();
            thisDependentVals.forEach(function(elem){
                $('#' + thisName + ' option[value="' + elem + '"]').show();
            });
        }
        
        lastName = thisName;
        lastVal = thisVal;
    }
}
</script>


Line 2 must be updated with the names of the select questions used in order of dependency, with the independent question listed first.

Lines 3-9 must be updated with the dependent nature of the questions.
answered Feb 6, 2017 by Zachary Platinum Sawtooth Software, Inc. (171,525 points)
I was hoping it would become a permanent fixture within Sawtooth Software rather than a useful tool via the forum and/or on the Sawtooth Software website. It has certainly become a popular feature in many of the surveys I conduct as a respondent with other software.

I have seen some surveys where they dump all questions on one page (our Australian Census use this feature a great deal). Rather than use skips, they use this approach of displaying the child / drill down question if the parent question is answered appropriately.

I think it looks good but it gives us choice in our programming endeavours and clients love choice too. I'm sure they would be impressed with this look.

Thanks Zachary for pushing it in the right direction. I hope it gains acceleration and popularity that encourages the developers to work with it.
Hey Zach,

thank you for putting that up. Could you please be a little bit verbose where we need to put what.

So for complete newbies:

- what question type
- where to put what code (header, footer, html, advanced..?)

That would be of great help.

Many thanks.
The latest Drilldown code - and its documentation - can be found here:

https://sawtoothsoftware.com/community-question-library/1767-drilldown-dropdowns

Here's an exemplary excerpt from the code:

AddDrilldown('Drilldown1', 'Drilldown2', drilldownSettings.disabled, // when Drilldown1 is unanswered, disable Drilldown2
    { // when Drilldown1 = 1, show the first three options of Drilldown2
            when: 1,
            then: [1, 2, 3]
    }, { // when Drilldown1 = 2, show the middle three options of Drilldown2
            when: 2,
            then: [4, 5, 6]
    }, { // when Drilldown1 = 3, show the last three options of Drilldown2
            when: 3,
            then: [7, 8, 9]
    });


This makes the select question "Drilldown2" dependent on select question "Drilldown1."  When the first option of Drilldown1 is selected, options 1, 2, and 3 of Drilldown2 are shown; when the second option of Drilldown1 is selected, options 4, 5, and 6 of Drilldown2 are shown; et cetera.
Thank you Zach. I have already checked that one out and unfortunately my implementation does not work.

I have right now two select questions on one display (w/o page break).

The first one (named Q2b) has in its footer following code:
<style>
  .drilldown_clone {
      display: none;
      }
</style>

<script>
$(document).ready(function(){
  var drilldownSettings = {
     empty: 1,
     disabled: 2,
     hidden: 3
  }
  
  AddDrilldown('Q2b', 'Q2b1', drilldownSettings.hidden, // when Drilldown1 is unanswered, disable Drilldown2
  { // when Drilldown1 = 1, show the first three options of Drilldown2
    when: 1,
    then: [1, 2, 3] },
    { // when Drilldown1 = 2, show the middle three options of Drilldown2
    when: 2,
    then: [4, 5, 6]
    }, { // when Drilldown1 = 3, show the last three options of Drilldown2
    when: 3,
    then: [7, 8, 9]
});



function AddDrilldown(independentDropdown, dependentDropdown) {
  // Move dependent dropdown
  $('#' + independentDropdown).after($('#' + dependentDropdown));
  
  // Clone
  var clone = $('#' + dependentDropdown).clone();
  $(clone).attr('id', '');
  $(clone).attr('name', '');
  $(clone).addClass('drilldown_clone');
  $(clone).attr('data-cloneof', dependentDropdown);
  $(clone).children('option').removeAttr('selected');
  $('#' + dependentDropdown).after(clone);
  
  // CSS
  $('#' + independentDropdown + ', #' + dependentDropdown).css('margin', '4px');
  $('#' + dependentDropdown).css('width', $(clone).css('width'));
  
  // Change
  var args = arguments;
  $('#' + independentDropdown).change(function(){
    var independentValue = SSI_GetValue(independentDropdown);
    var dependentValue = SSI_GetValue(dependentDropdown);
    var clone = $('#' + dependentDropdown).siblings('.drilldown_clone[data-cloneof="' + dependentDropdown + '"]');
   
    $('#' + dependentDropdown + ' > option:not(:first-child)').remove();
    if (independentValue) {
      $('#' + dependentDropdown).prop('disabled', false);
      $('#' + dependentDropdown).show();
      
      for (var i = 3; i < args.length; i++) {
        var arg = args[i];
        if (arg.when == independentValue) {
           arg.then.forEach(function(t) {
           $('#' + dependentDropdown).append($(clone).children('option[value="' + t + '"]').clone());
           if (t == dependentValue) {
             $('#' + dependentDropdown).val(t);
             }
        });
        break;
  }
 }
}

else {
  switch (args[2]) {
    case 2:
      $('#' + dependentDropdown).prop('disabled', true);
      break;
    case 3:
      $('#' + dependentDropdown).hide();
      break;
      }
    }
   
    $('#' + dependentDropdown).change();
});

$('#' + independentDropdown).change();
}
</script>


The second (named "Q2b1", the dependant) has the following code in its footer:
<style> #[% QuestionName() %]_div { display: none; } </style>

they have both predefined list with combo box answer possibility.

Do you know what I have to alter to get it working?

Many, many thanks.
What incorrect behavior are you observing?  Are there any error messages in your browser's console on this page?  You can usually open a browser's console by pressing F12 and navigating to a Console tab; error messages in the console are typically printed in red text.

Do the three default dropdowns that come from the question library work before making any changes?
...