Please try the following:
In the CBC's "SSI_Comment" portion, disable verification.
Give the free format question two variables, both whole numbered radio buttons. Name them "_response" and "_none."
Set the body of the free format question to this:
[% Begin Unverified Perl
# --------------------
# Instructions
# --------------------
# This question serves to help users create free format CBCs.
# It's core functionality is the same as another question in the Sawtooth Software Question Library.
# Whereas the other question has HTML hard coded into the question, this question programmatically generates the HTML using Perl.
# Users familiar with Perl may have an easier time using and modifying this question for their needs.
# It is recommended that you add this question to your questionnaire, adjust the settings and make any other additional changes to the code, and finally copy-and-paste the question throughout your CBC exercise.
# This question's name must consist of a base name appended with the CBC task related to this free format question. For example, "mycbcRandom1" and "mycbcFixed2".
# The header of the CBC exercise must be given the standard HTML comment for free format CBCs:
# The standard HTML comment can be found in the free format CBC documentation in Lighthouse Studio Help.
# The comment should be set to not run verification.
# The error messages to be used by this free format question can be modified in this question's custom JavaScript verification.
# --------------------
# Settings
# --------------------
# General parameters
my $nameOfCbc = 'cbc';
my $numberOfAttributes = 4;
my $numberOfConcepts = 2;
my $numberOfTasks = 12;
my @positionsOfFixedTasks = (); # positions of fixed tasks throughout the tasks, one-based and ordered from lowest to greatest
# Response type
my $responseType = 1; # 1 - discrete choice, 2 - best worst, 3 - constant sum
my $requireResponse = 1; # 1 - require response, 0 - do not require response
my $discreteButtonText = 'Select';
my $bestWorstBestButtonText = 'Best';
my $bestWorstWorstButtonText = 'Worst';
my $constantSumTotal = 100;
my $constantSumLeftInputLabel = '';
my $constantSumRightInputLabel = '';
my $constantSumLeftTotalLabel = 'Total:';
my $constantSumRightTotalLabel = '';
# None option
my $noneOption = 2; # 0 - do not include, 1 - traditional, 2 - dual response
my $dualNoneRequireResponse = 1; # 1 - require response if dual response none included, 0 - not required
my $traditionalNonePosition = 1; # 1 - concept below task, 2 - last concept in task
#my $noneOptionText = 'NONE: I wouldn\'t choose any of these.';
my $noneOptionText = 'Given what you know about the market, would you really buy the XXXXXXXXX you chose above?';
my $dualNoneYesText = 'Yes';
my $dualNoneNoText = 'No';
# Formatting
my $mobile = 1; # 0 - maintain desktop layout, 1 - horizontal CBC from mobile screens, 2 - vertical CBC from mobile screens
my $attributeLabels = 0; # 0 - do not display attribute labels, 1 - display attribute labels left of concepts, 2 - display attribute labels inside concepts
my @conceptLabels = (); # concept labels, if any
# --------------------
# Generate page contents
# --------------------
my $cbcTaskNumber;
my $cbcTask;
findCbcTask();
my $customCbcCode;
$customCbcCode .= generateHtml();
$customCbcCode .= generateCss();
return $customCbcCode;
# Find CBC task name based off this question's name
sub findCbcTask {
my $qname = QUESTIONNAME();
$qname =~ m/((Random|Fixed)([0-9])+)$/; # Match all numeric characters that come at the end of the question name
$cbcTaskNumber = $3;
$cbcTask = $nameOfCbc . '_' . $1;
}
# Generate HTML
sub generateHtml {
my $output;
$output .= generateTaskNumberHtml();
$output .= generateMobileCbcHtml();
$output .= generateTaskNavigationHtml();
my $responseTypeClass = findResponseTypeClass();
$output .= generateAttributeLabelsHtml($responseTypeClass);
$output .= generateConceptsHtml($responseTypeClass);
$output .= generateTraditionalNoneConceptHtml($responseTypeClass);
$output .= '</div>';
$output .= generateTotalHtml($constantSumLeftTotalLabel, $constantSumRightTotalLabel);
$output .= '</div>';
$output .= generateDualNoneConceptHtml($responseTypeClass);
$output .= generateHtmlForJavaScript();
return $output;
}
# Generate HTML for task number
sub generateTaskNumberHtml {
my $printableTaskNumber;
if ($cbcTask =~ m/_Fixed/) {
$printableTaskNumber = $positionsOfFixedTasks[$cbcTaskNumber - 1];
}
else {
$printableTaskNumber = $cbcTaskNumber;
foreach my $fixedTaskPosition (@positionsOfFixedTasks) {
if ($printableTaskNumber >= $fixedTaskPosition) {
$printableTaskNumber++;
}
else {
last;
}
}
}
return '<div>(' . $printableTaskNumber . ' of ' . $numberOfTasks . ')</div>';
}
# Generate HTML for mobile navigation mode
sub generateMobileCbcHtml {
my $mobileClass;
if ($mobile == 1) {
$mobileClass = 'mobile_horizontal';
}
elsif ($mobile == 2) {
$mobileClass = 'mobile_vertical';
}
else {
$mobileClass = 'no_mobile';
}
return '<div class="' . $mobileClass . ' ">';
}
# Find HTML class to use representing the CBC response type
sub findResponseTypeClass {
if ($responseType == 2) {
return 'best_worst';
}
elsif ($responseType == 3) {
return 'constant_sum';
}
return 'discrete';
}
# Generate HTML for navigating between concepts
sub generateTaskNavigationHtml {
my $output;
$output .= '<div class="task_controls">';
$output .= '<div class="task_nav">';
$output .= '<div class="carousel_prev carousel_arrow"></div>';
$output .= '<div class="task_nav_dots">';
for (my $concept = 1; $concept <= $numberOfConcepts; $concept++) {
$output .= '<div class="nav_dot dot_' . $concept . '"></div>';
}
$output .= '</div>';
$output .= '<div class="carousel_next carousel_arrow"></div>';
$output .= '</div></div>';
return $output;
}
# Generate HTML for attribute labels
sub generateAttributeLabelsHtml {
my ($responseTypeClass) = @_;
my $output;
$output .= '<div class="cbc_task ' . $responseTypeClass . ' owl-carousel hide_for_processing">';
$output .= '<div class="attribute_label_column">';
my $sharedAttributeLabelClasses = 'cbc_cell attribute_label_cell';
# Concept labels
if (scalar @conceptLabels) {
$output .= '<div class="' . $sharedAttributeLabelClasses . ' top_corner_label concept_label_cell"></div>';
}
# Attribute labels
for (my $attribute = 1; $attribute <= $numberOfAttributes; $attribute++) {
my $firstAttributeClass = $attribute == 1 ? 'first_att' : '';
$output .= '<div class="' . $sharedAttributeLabelClasses . ' att_' . $attribute . ' ' . $firstAttributeClass . '">';
$output .= '<span class="att_label_text">';
$output .= CBCATTRIBUTELABEL($cbcTask, $attribute);
$output .= '</span></div>';
}
$output .= '<div class="cbc_cell concept_cell cbc_response_cell attribute_label_cell bottom_corner_label"></div>';
$output .= '</div>';
return $output;
}
(cont.)