Have an idea?

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

NONE Option in a semantic differential

How can I add the option, "I can´t assess it" what´t like a NONE Option in a semantic differential?
asked Feb 2, 2017 by Isi
retagged Feb 2, 2017 by Walter Williams
Are you interested in having a none option for each row or one none option for the entire question?
for each row please, because I have 3 questions each with a semantic differential. But they are all separate.

I would also appreciate it when you could explain how both works, just in case I would need both possibilities :)

1 Answer

0 votes
 
Best answer
Alright.  I've got per-row done; I'll throw together the other way after this.

Start by placing a checkbox-type select question immediately following the semantic diff.  The select needs the same list as the sem diff's left or right list.  You can give it this code to keep it hidden from respondents:

<style>
#[% QuestionName() %]_div {
    display: none;
}
</style>


Now give the semantic diff this code:

<script>
$(document).ready(function(){
    var selectQ = $('#[% QuestionName() %]_div').nextAll('.question.select')[0].id.replace('_div', '');
    var list = $('input[name=hid_list_' + selectQ + ']').val().split(',').map(Number);
    
    $('#[% QuestionName() %]_div .column_header_row').append('<td>NONE</td>');
    list.forEach(function(item){
        $('#' + selectQ + '_' + item).closest('.response_row').find('.option_cell').remove();
        $('#[% QuestionName() %]_' + item + '_row').append('<td></td>');
        $('#[% QuestionName() %]_' + item + '_row td:last-child').append($('#' + selectQ + '_' + item).closest('.response_row'));
        
        if (SSI_GetValue(selectQ + '_' + item)) {
            $('#[% QuestionName() %]_' + item).find('.ui-slider').slider('disable');
        }
    });
})

function SSI_CustomGraphicalCheckbox(graphicalObj, inputObj, bln) {
    var selectQ = $('#[% QuestionName() %]_div').nextAll('.question.select')[0].id.replace('_div', '');
    var regex = new RegExp(selectQ + '_([0-9]+)');
    var match = inputObj.name.match(regex);
    if (match) {
        var item = Number(match[1]);
        if (bln) {
            $('#[% QuestionName() %]_' + item).find('.ui-slider').slider('disable');
            $('#[% QuestionName() %]_' + item).find('input').val('');
            $('#[% QuestionName() %]_' + item).find('.ui-slider-handle').css('left', '50%');
        }
        else {
            $('#[% QuestionName() %]_' + item).find('.ui-slider').slider('enable');
        }
    }
}
</script>


If you want to require that the respondent either answers the SD row or checks the checkbox, disable "Require response" in the SD settings and use this custom JavaScript verification:

var selectQ = $('#[% QuestionName() %]_div').nextAll('.question.select')[0].id.replace('_div', '');
var list = $('input[name=hid_list_' + selectQ + ']').val().split(',').map(Number);

list.forEach(function(item){
    var sdResp = SSI_GetValue('[% QuestionName() %]_' + item);
    var checkResp = SSI_GetValue(selectQ + '_' + item);
    if (!sdResp && !checkResp) {
        strErrorMessage = 'Error.';
    }
})
answered Feb 2, 2017 by Zachary Platinum Sawtooth Software, Inc. (83,675 points)
Per-question done.

Again, start by putting a checkbox-type select question immediately after the semantic diff.  It must have one list item.  You can hide it with the same CSS from earlier.

Now give the semantic diff this code:

<script>
$(document).ready(function(){
    var selectQ = $('#[% QuestionName() %]_div').nextAll('.question.select')[0].id.replace('_div', '');
    $('#[% QuestionName() %]_div .question_body').append($('#' + selectQ + '_div .response_row'));
    
    if (SSI_GetValue(selectQ + '_1')) {
        $('#[% QuestionName() %]_div .ui-slider').slider('disable');
    }
})

function SSI_CustomGraphicalCheckbox(graphicalObj, inputObj, bln) {
    var selectQ = $('#[% QuestionName() %]_div').nextAll('.question.select')[0].id.replace('_div', '');
    if (inputObj.name.startsWith(selectQ + '_')) {
        if (bln) {
            $('#[% QuestionName() %]_div .ui-slider').slider('disable');
            $('#[% QuestionName() %]_div .ui-slider input').val('');
            $('#[% QuestionName() %]_div .ui-slider .ui-slider-handle').css('left', '50%');
        }
        else {
            $('#[% QuestionName() %]_div .ui-slider').slider('enable');
        }
    }
}
</script>


If you want to require the SD only when the checkbox is not selected, disable the SD's "Require response" and use this custom JavaScript verification:

var selectQ = $('#[% QuestionName() %]_div').nextAll('.question.select')[0].id.replace('_div', '');

if (!SSI_GetValue(selectQ + '_1')) {
    $('#[% QuestionName() %]_div .slider_container').each(function(){
        if (!SSI_GetValue(this.id)) {
            strErrorMessage = 'Error.';
        }
    });
}
Thank you so much! That was a great help!
Almost everything worked with your codes until one thing:

The None Option is in the same row as the scale of the semantic differential, but my problem is now, that I can choose both. The None option AND a number of the scale, not either or.

You said I have to disable the function "Require Response" in the SD settings and I have to use the Java Script verification in the SD question:

var selectQ = $('#[% QuestionName() %]_div').nextAll('.question.select')[0].id.replace('_div', '');
var list = $('input[name=hid_list_' + selectQ + ']').val().split(',').map(Number);
 
list.forEach(function(item){
    var sdResp = SSI_GetValue('[% QuestionName() %]_' + item);
    var checkResp = SSI_GetValue(selectQ + '_' + item);
    if (!sdResp && !checkResp) {
        strErrorMessage = 'Error.';
    }
})


I did both, but the problem of choosing both at the same time is not solved yet.

Do I have to change anything in the code additionally? I also inserted the name of my select/none question in the brackets, but it didn´t work.

Or do I have to change anything additional in the settings of the Select/None Question?

I would be so grateful about your help.

Thank you,

Isi

 








There´s only one thing, which I´m not able to make:
A few thoughts:

* All the code I've posted in this question require no changes.  Leave the QuestionName Sawtooth Scripts as I put them.

* You're using sliders instead of radio buttons in the semantic diff, right?  The code should work for sliders, but would need to be changed for radio buttons.

* If neither of those are the source of the problem, what browser are you observing the problem in?
I use radio buttons in the semantic differential,  no sliders. So that's the source of the problem..

Could you please give me the Code for buttons?

Thank you for your fast answers!
Sorry for the delay; had to create some tangentially-related code to do your request justice.  Here's the replacement for the code that the SD needs:

<script>
$(document).ready(function(){
    var numberOfAnchors = 4;

    var selectQ = $('#[% QuestionName() %]_div').nextAll('.question.select')[0].id.replace('_div', '');
    var list = $('input[name=hid_list_' + selectQ + ']').val().split(',').map(Number);
    
    $('#[% QuestionName() %]_div .column_header_row').append('<td>NONE</td>');
    list.forEach(function(item){
        $('#' + selectQ + '_' + item).closest('.response_row').find('.option_cell').remove();
        $('#[% QuestionName() %]_' + item + '_row').append('<td></td>');
        $('#[% QuestionName() %]_' + item + '_row td:last-child').append($('#' + selectQ + '_' + item).closest('.response_row'));
         
        if (SSI_GetValue(selectQ + '_' + item)) {
            for (var i = 1; i <= numberOfAnchors; i++) {
                disableGraphicalRadio('[% QuestionName() %]_' + item + '_' + i);
            }
        }
    });
    
    $(document).on('customGraphicalCheckbox', function(event, graphicalObj, inputObj, bln){
        var selectQ = $('#[% QuestionName() %]_div').nextAll('.question.select')[0].id.replace('_div', '');
        var regex = new RegExp(selectQ + '_([0-9]+)');
        var match = inputObj.name.match(regex);
        if (match) {
            var item = Number(match[1]);
            if (bln) {
                for (var i = 1; i <= numberOfAnchors; i++) {
                    disableGraphicalRadio('[% QuestionName() %]_' + item + '_' + i);
                }
            }
            else {
                for (var i = 1; i <= numberOfAnchors; i++) {
                    enableGraphicalRadio('[% QuestionName() %]_' + item + '_' + i);
                }
            }
        }
    });
})

// Disabled graphicals
GLOBAL_SAWTOOTH_DISABLEDRADIOS = [];
GLOBAL_SAWTOOTH_DISABLEDCHECKS = [];

function disableGraphicalRadio(id) {
    // Parse ID
    var match = id.match(/^(.*)_([0-9]+)$/);
    var name = match[1];
    var disabled = Number(match[2]);
    
    // Reset
    if (SSI_GetValue(name) == disabled) {
        SSI_RadioReset(name);
    }
    
    // CSS
    $('#' + id + '_graphical').css('opacity', 0.5);
    $('#' + id + '_graphical').closest('.clickable').andSelf().css('cursor', 'default');
    
    // Add to global
    for (var i = 0; i < GLOBAL_SAWTOOTH_DISABLEDRADIOS.length; i++) {
        if (GLOBAL_SAWTOOTH_DISABLEDRADIOS[i].name == name) {
            if (GLOBAL_SAWTOOTH_DISABLEDRADIOS[i].disabled.indexOf(disabled) == -1) {
                GLOBAL_SAWTOOTH_DISABLEDRADIOS[i].disabled.push(disabled);
            }
            return;
        }
    }
    GLOBAL_SAWTOOTH_DISABLEDRADIOS.push({
        name: name,
        disabled: [disabled],
        value: SSI_GetValue(name)
    });
}

function enableGraphicalRadio(id) {
    // Parse ID
    var match = id.match(/^(.*)_([0-9]+)$/);
    var name = match[1];
    var disabled = Number(match[2]);
    
    // CSS
    $('#' + id + '_graphical').css('opacity', 1);
    $('#' + id + '_graphical').closest('.clickable').andSelf().css('cursor', 'pointer');
    
    // Remove from global
    for (var i = 0; i < GLOBAL_SAWTOOTH_DISABLEDRADIOS.length; i++) {
        if (GLOBAL_SAWTOOTH_DISABLEDRADIOS[i].name == name) {
            GLOBAL_SAWTOOTH_DISABLEDRADIOS[i].disabled.splice(GLOBAL_SAWTOOTH_DISABLEDRADIOS[i].disabled.indexOf(disabled), 1);
            if (!GLOBAL_SAWTOOTH_DISABLEDRADIOS[i].disabled.length) {
                GLOBAL_SAWTOOTH_DISABLEDRADIOS.splice(i, 1);
            }
            break;
        }
    }
}

function disableGraphicalCheck(id) {
    // Reset
    if (SSI_GetValue(id)) {
        SSI_SetSelect(id, false);
    }
    
    // CSS
    $('#' + id + '_graphical').css('opacity', 0.5);
    $('#' + id + '_graphical').closest('.clickable').andSelf().css('cursor', 'default');

    // Add to global
    if (GLOBAL_SAWTOOTH_DISABLEDCHECKS.indexOf(id) == -1) {
        GLOBAL_SAWTOOTH_DISABLEDCHECKS.push(id);
    }
}

function enableGraphicalCheck(id) {
    // CSS
    $('#' + id + '_graphical').css('opacity', 1);
    $('#' + id + '_graphical').closest('.clickable').andSelf().css('cursor', 'pointer');
    
    // Remove from global
    GLOBAL_SAWTOOTH_DISABLEDCHECKS.splice(GLOBAL_SAWTOOTH_DISABLEDCHECKS.indexOf(id), 1);
}

// Graphical radio event
$(document).on('customGraphicalRadiobox', function(event, graphicalObj, inputObj){
    for (var i = 0; i < GLOBAL_SAWTOOTH_DISABLEDRADIOS.length; i++) {
        if (GLOBAL_SAWTOOTH_DISABLEDRADIOS[i].name == inputObj.name) {
            if (GLOBAL_SAWTOOTH_DISABLEDRADIOS[i].disabled.indexOf(SSI_GetValue(inputObj.name)) != -1) {
                SSI_RadioReset(inputObj.name);
                if (GLOBAL_SAWTOOTH_DISABLEDRADIOS[i].value) {
                    SSI_SetSelect(inputObj.name + '_' + GLOBAL_SAWTOOTH_DISABLEDRADIOS[i].value, true);
                }    
            }
            else {
                GLOBAL_SAWTOOTH_DISABLEDRADIOS[i].value = SSI_GetValue(inputObj.name);
            }
            break;
        }
    }
});

// Graphical check event
$(document).on('customGraphicalCheckbox', function(event, graphicalObj, inputObj, bln){
    GLOBAL_SAWTOOTH_DISABLEDCHECKS.forEach(function(id){
        if (SSI_GetValue(id)) {
            SSI_SetSelect(id, false);
        }
    });
});

// Graphical event triggers
function SSI_CustomGraphicalRadiobox(graphicalObj, inputObj) {
    $(document).trigger('customGraphicalRadiobox', [graphicalObj, inputObj]);
}

function SSI_CustomGraphicalCheckbox(graphicalObj, inputObj, bln) {
    $(document).trigger('customGraphicalCheckbox', [graphicalObj, inputObj, bln]);
}
</script>


Line 3 needs to be updated with the number of radio buttons in each row.
...