Have an idea?

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

Question Library - Not Applicable: Per Question with multiple check boxes

This question is most likely aimed at Zachary ...

I have a question where I would like to apply the Not Applicable: Per Question feature from the QUESTION LIBRARY. The key difference is I would like to display 2 check boxes - one for None and one for Don't know.

I would like to apply this technique to both an O/E question and a numeric question.

So the respondent has the choice of entering a response in the text box or numeric box) or selecting one of the check boxes.

Thank you.
asked Nov 20, 2017 by Paul Moon Platinum (74,405 points)

1 Answer

0 votes
 
Best answer
Paul, I had Zach help me with the same thing a while back and this is the code I have from that.  Create your select question with the None and Don't Know options and put this in the footer.

<style>
#[% QuestionName() %]_div {
    display: none;
}
 
.error_quest_highlight2 {
    border: 1px solid red !important;
}
</style>
 
<script>
$(window).on('load', function(){
    // Question
    var question = $('#[% QuestionName() %]_div').prevAll('.question')[0].id.replace(/_div/, '');
    var qdiv = $('#' + question + '_div');
     
    // Move N/A field
    $(qdiv).find('.question_body').append($('#[% QuestionName() %]_div .response_row'));
     
    // N/A click event
    $(document).on('customGraphicalCheckbox', function(event, graphicalObj, inputObj, bln){
        if (inputObj.name.startsWith('[% QuestionName() %]_')) {
            // Disable and clear question
            if (SSI_GetValue('[% QuestionName() %]_1') || SSI_GetValue('[% QuestionName() %]_2')) {
                // Inputs, textareas, selects
                $(qdiv).find('input[type=text]').val('').prop('disabled', true);
                $(qdiv).find('input[type=tel]').val('').prop('disabled', true);
                $(qdiv).find('textarea').val('').prop('disabled', true);
                $(qdiv).find('select').val('').prop('disabled', true);
                 
                // Graphical radios and checks
                $(qdiv).find('input[type=radio]').each(function(){
                    SSI_RadioReset(this.name);
                    SSI_DisableGraphicalInput(this.id);
                });
                $(qdiv).find('input[type=checkbox]').each(function(){
                    if (this.id != '[% QuestionName() %]_1' && this.id != '[% QuestionName() %]_2') {
                        SSI_SetSelect(this.id, false);
                        SSI_DisableGraphicalInput(this.id);
                    }
                });
                 
                // Semantic diffs
                $(qdiv).find('.ui-slider').each(function(){
                    $(this).find('input').val('');
                    $(this).find('.ui-slider-handle').css('left', '50%');
                    $(this).slider('disable');
                });
                 
                // Drag-and-drop ranking
                $(qdiv).find('.draggable_button').each(function(){
                    $(this).find('input').val('');
                    $(this).find('.rank_number').text('');
                });
                $(qdiv).find('.unranked_sort_area').append($(qdiv).find('.ranked_sort_area .draggable_button'));
                $(qdiv).find('.ui-sortable').sortable('option', 'cancel', '.draggable_button');
            }
         
            // Enable question
            else {
                // Inputs, textareas, selects
                $(qdiv).find('input[type=text]').prop('disabled', false);
                $(qdiv).find('input[type=tel]').prop('disabled', false);
                $(qdiv).find('textarea').prop('disabled', false);
                $(qdiv).find('select').prop('disabled', false);
 
                // Graphical radios and checks
                $(qdiv).find('input[type=radio]').each(function(){
                    SSI_EnableGraphicalInput(this.id);
                });
                $(qdiv).find('input[type=checkbox]').each(function(){
                    if (this.id != '[% QuestionName() %]_1' && this.id != '[% QuestionName() %]_2') {
                        SSI_EnableGraphicalInput(this.id);
                    }
                });
 
                // Semantic diffs
                $(qdiv).find('.ui-slider').each(function(){
                    $(this).slider('enable');
                });
                 
                // Drag-and-drop ranking
                $(qdiv).find('.ui-sortable').sortable('option', 'cancel', '');
            }
        }
    });
    $(document).trigger('customGraphicalCheckbox', [undefined, {name: '[% QuestionName() %]_1'}, SSI_GetValue('[% QuestionName() %]_1')]);
    $(document).trigger('customGraphicalCheckbox', [undefined, {name: '[% QuestionName() %]_2'}, SSI_GetValue('[% QuestionName() %]_2')]);
})
 
function SSI_CustomGraphicalCheckbox(graphicalObj, inputObj, bln) {
    $(document).trigger('customGraphicalCheckbox', [graphicalObj, inputObj, bln]);
}
</script>
answered Nov 20, 2017 by Jay Rutherford Gold (31,740 points)
selected Nov 20, 2017 by Paul Moon
Then in the advanced custom javascript verification area use this:

// Grid parameters (must be updated if using grid)
var gridInfo = {
    orientation: 'r', // 'r' for row-oriented grid, 'c' for col-oriented grid
    constantSumOrRanking: [] // must be filled with any rows / columns that are constant sum or ranking
}
 
var question = $('#[% QuestionName() %]_div').prevAll('.question')[0].id.replace(/_div/, '');
var qdiv = $('#' + question + '_div');
var err;
 
if (!SSI_GetValue('[% QuestionName() %]_1') && !SSI_GetValue('[% QuestionName() %]_2')) {
    // Radio select, combo select
    if ($(qdiv).hasClass('select') && $(qdiv).find('input[type=checkbox]').length == 1) {
        err = !SSI_GetValue(question);
    }
     
    // Numeric, open end
    else if ($(qdiv).hasClass('numeric') || $(qdiv).hasClass('openend')) {
        err = !$('#' + question).val().length;
    }
     
    // Non-tel ranking
    else if ($(qdiv).hasClass('ranking') && ($(qdiv).find('select').length || $(qdiv).find('.ui-sortable').length)) {
        var list = $('input[name=hid_list_' + question + ']').val().split(',').map(Number);
        err = true;
        for (var i = 0; i < list.length; i++) {
            if (SSI_GetValue(question + '_' + list[i])) {
                err = false;
                break;
            }
        }
    }
     
    // Sem diff
    else if ($(qdiv).hasClass('semanticdiff')) {
        var list = $('input[name=hid_list_' + question + ']').val().split(',').map(Number);
        err = false;
        for (var i = 0; i < list.length; i++) {
            if (!SSI_GetValue(question + '_' + list[i])) {
                err = true;
                break;
            }
        }
    }
     
    // Constant sum, tel ranking
    else if ($(qdiv).hasClass('constantsum') || $(qdiv).hasClass('ranking')) {
        var list = $('input[name=hid_list_' + question + ']').val().split(',').map(Number);
        err = true;
        for (var i = 0; i < list.length; i++) {
            if ($('#' + question + '_' + list[i]).val().length) {
                err = false;
                break;
            }
        }
    }
     
    // Grid
    else if ($(qdiv).hasClass('grid')) {
        var rows = $('input[name=hid_row_list_' + question + ']').val().split(',').map(Number);
        var cols = $('input[name=hid_col_list_' + question + ']').val().split(',').map(Number);
         
        // Row-oriented
        if (gridInfo.orientation == 'r') {
            var firstCol = cols[0];
            for (var r = 0; r < rows.length && !err; r++) {
                var row = rows[r];
 
                // Radio
                if ($('#' + question + '_r' + row + '_' + firstCol + '[type=radio]').length) {
                    err = !SSI_GetValue(question + '_r' + row);
                }
 
                // Check
                else if ($('#' + question + '_r' + row + '_c' + firstCol + '[type=checkbox]').length) {
 
                }
 
                // Combo
                else if ($('select#' + question + '_r' + row + '_c' + firstCol).length && gridInfo.constantSumOrRanking.indexOf(row) == -1) {
                    for (var c = 0; c < cols.length && !err; c++) {
                        var col = cols[c];
                        err = !SSI_GetValue(question + '_r' + row + '_c' + col);
                    }
                }
 
                // Open end, numeric
                else if (gridInfo.constantSumOrRanking.indexOf(row) == -1) {
                    for (var c = 0; c < cols.length && !err; c++) {
                        var col = cols[c];
                        err = !$('#' + question + '_r' + row + '_c' + col).val().length;
                    }
                }
 
                // Combo ranking
                else if ($('select#' + question + '_r' + row + '_c' + firstCol).length) {
                    err = true;
                    for (var c = 0; c < cols.length && err; c++) {
                        var col = cols[c];
                        err = !SSI_GetValue(question + '_r' + row + '_c' + col);
                    }
                }
 
                // Constant sum, tel ranking
                else {
                    err = true;
                    for (var c = 0; c < cols.length && err; c++) {
                        var col = cols[c];
                        err = !$('#' + question + '_r' + row + '_c' + col).val().length;
                    }
                }
            }
        }
         
        // Col-oriented
        else {
            var firstRow = rows[0];
            for (var c = 0; c < cols.length && !err; c++) {
                var col = cols[c];
 
                // Radio
                if ($('#' + question + '_c' + col + '_' + firstRow + '[type=radio]').length) {
                    err = !SSI_GetValue(question + '_c' + col);
                }
 
                // Check
                else if ($('#' + question + '_r' + firstRow + '_c' + col + '[type=checkbox]').length) {
 
                }
 
                // Combo
                else if ($('select#' + question + '_r' + firstRow + '_c' + col).length && gridInfo.constantSumOrRanking.indexOf(col) == -1) {
                    for (var r = 0; r < rows.length && !err; r++) {
                        var row = rows[r];
                        err = !SSI_GetValue(question + '_r' + row + '_c' + col);
                    }
                }
 
                // Open end, numeric
                else if (gridInfo.constantSumOrRanking.indexOf(col) == -1) {
                    for (var r = 0; r < rows.length && !err; r++) {
                        var row = rows[r];
                        err = !$('#' + question + '_r' + row + '_c' + col).val().length;
                    }
                }
 
                // Combo ranking
                else if ($('select#' + question + '_r' + firstRow + '_c' + col).length) {
                    err = true;
                    for (var r = 0; r < rows.length && err; r++) {
                        var row = rows[r];
                        err = !SSI_GetValue(question + '_r' + row + '_c' + col);
                    }
                }
 
                // Constant sum, tel ranking
                else {
                    err = true;
                    for (var r = 0; r < rows.length && err; r++) {
                        var row = rows[r];
                        err = !$('#' + question + '_r' + row + '_c' + col).val().length;
                    }
                }
            }
        }
    }
 
    // Free format
    else if ($(qdiv).hasClass('freeformat')) {
        var selects = $(qdiv).find('input[type=radio], select');
        for (var i = 0; i < selects.length && !err; i++) {
            err = !SSI_GetValue(selects[i].name);
        }
 
        var inputs = $(qdiv).find('input[type=tel], input[type=text], textarea');
        for (var i = 0; i < inputs.length && !err; i++) {
            err = !$(inputs[i]).val().length;
        }
    }
}
 
// Error
$(qdiv).removeClass('error_quest_highlight2');
$('#' + question + '_err2').remove();
 
if (err) {
    strErrorMessage = 'Question must be answered or a checkbox must be selected.';
 
    $(qdiv).removeClass('error_quest_highlight');
    $('#' + question + '_err').remove();
    $(qdiv).addClass('error_quest_highlight2');
    $(qdiv).prepend('<div id="' + question + '_err2" class="question_error_box error_messages"></div>');
    $('#' + question + '_err2').append('<div class="question_errors">' + strErrorMessage + '</div>');
}
Thanks Jay.

Will this work with an O/E and also with a  numeric question?

I plan to test it  in an hour or so.

Thanks mate.
Yes to both.  I just did a quick test to make sure.  If you have any problems with it let me know and I can send you a file.
Thanks heaps Jay.

And thanks also to Zachary for the usual wizardry.

I'll reach back to you via this post top confirm I have it working.
Jay, just completed the testing. Awesome!!!

Works just nice. Thanks again mate for chipping in.

And I can't say enough thank you's to Mr Anderson also for some top notch programming.
Jay, I was wondering if this worked with any number of check boxes? I can test it tomorrow but wasn't sure if you was aware of this working for 3 or 4 check boxes for example?
Actually, it looks like it doesn't work. Just tested it and unfortunately it failed. Not that I needed it but I was curious.
If you look through the code there are several spots where I can see he added script to include "_1" or "_2".  You could potentially look through that and attempt to modify to include additional 'or' statements and that would probably do it.  I can't recall if I've done that myself or not.
Jay, I had this working nicely when testing in Google Chrome and then noticed it does not work in Internet Explorer. I'll send an email to Zachary hoping to gain a magic fix. Stay tuned ...
Looks like IE doesn't support startsWith.  Replace that line of the code with this:

if (/^[% QuestionName() %]_/.test(inputObj.name)) {
I just tested that out in IE and looks like it's working across browsers now on my end.
Just tested it out on Chrome, IE and my iPhone. Works like a charm.

Awesome as always Zachary.

I'm running out of things to say?

Can't thank you enough for another rescue mission!
Agree Jay. Zachary to rescue again! Gotta love his work.
...