Have an idea?

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

Generating counts for highlighted words/phrases


For either the "Highlighting: Words" or "Highlighting: Custom Ranges" questions in the Community Question Library, is there a way to generate the counts for each word or phrase that is highlighted?  

asked Apr 8 by Quentin (470 points)
You want to know how many respondents selected particular words/phrases, correct?  Do you need this info at survey runtime, or are you just looking to analyze existing data in this way?

It's not a built-in feature of either question, but it could be done with some additional work.  I'm imagining it would be easier to count words from "Highlighting: Words" than phrases from "Highlighting: Custom Ranges" if using either question is acceptable to you.
Yes, we'd like to know how many respondents selected particular words/phrases.  We haven't programmed the survey yet, but if we could be able to see the info at survey runtime in the admin module that would be great.

I think "Highlighting: Words" should be okay.  If we need to use certain phrases I can probably manually modify the spans that can be highlighted like you mentioned in this post:

1 Answer

0 votes
Best answer
Glad to see you've found that earlier forum post.  Sounds like you've done your research. :)

It may take a minute to setup all the quota questions, but I think I've got this working.  I started by adding a new checkbox variable named "_WordSelected" to the free format question and set its number of checkboxes to the same value used in the "$maxListItems" variable.  Then I replaced the HTML with this modified version:

<input name="[% QuestionName() %]_MasterData" id="[% QuestionName() %]_MasterData" type="hidden" value=""/>
<input name="[% QuestionName() %]_HighlightCount" id="[% QuestionName() %]_HighlightCount" type="hidden" value=""/>
[% Begin Unverified Perl
# Parameters
my $maxListItems = 100;

# Run
my $html;
for (my $i = 1; $i <= $maxListItems; $i++) {
    my $highlightVariable = QUESTIONNAME() . '_Highlight' . $i;
    $html .= '<input name="' . $highlightVariable . '" id="' . $highlightVariable . '" class="highlightInput" type="hidden" value=""/>';
    my $wordSelectedVariable = QUESTIONNAME() . '_WordSelected_' . $i;
    $html .= '<input name="' . $wordSelectedVariable . '" id="' . $wordSelectedVariable . '" type="hidden" value=""/>';
return $html;
End Unverified %]

<div id="[% QuestionName() %]_Text">

        Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
        Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
        Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
        Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.


<div class="highlightingButtonContainer">
    <button type="button" id="[% QuestionName() %]_ResetAllHighlighting">Reset All Highlighting</button>

#[% QuestionName() %]_Text {
    border: 1px solid black;
    border-radius: 18px;
    padding: 9px;
    background-color: #F6F6F6;

.highlightingButtonContainer {
    text-align: center;

.highlighted {
    background-color: yellow;

    // Add highlighting spans
    var openSpan = '<span class="highlightingSpan">';
    var closeSpan = '</span>';

    var html = $('#[% QuestionName() %]_Text').html();
    var len = html.length;
    var inHtmlTag = false;
    for (var h = 0; h < len; h++) {
        var p = html[h - 1];
        var c = html[h];
        var n = html[h + 1];
        if (c == '>') {
            inHtmlTag = false;
        if (c == '<' || inHtmlTag) {
            inHtmlTag = true;
        if (c.match(/\S/) && (p === undefined || p == '>' || p.match(/\s/))) {
            html = html.slice(0, h) + openSpan + html.slice(h);
            h += openSpan.length;
            len += openSpan.length;
        if (c.match(/\S/) && (n === undefined || n == '<' || n.match(/\s/))) {
            html = html.slice(0, h + 1) + closeSpan + html.slice(h + 1);
            h += closeSpan.length;
            len += closeSpan.length;
    $('#[% QuestionName() %]_Text').html(html);

    $('#[% QuestionName() %]_Text .highlightingSpan').each(function(index){
        $(this).attr('data-word', index + 1);
    // Set initial highlighting
    var highlightedWords = JSON.parse($('#[% QuestionName() %]_MasterData').val() || '[]');
        $('#[% QuestionName() %]_Text .highlightingSpan[data-word=' + highlightedWord + ']').addClass('highlighted');
    // Save
    var save = function(highlightedWords) {
        $('#[% QuestionName() %]_MasterData').val(JSON.stringify(highlightedWords));
        $('#[% QuestionName() %]_HighlightCount').val(highlightedWords.length)
        $('#[% QuestionName() %]_div .highlightInput').val('');
        $('[id^="[% QuestionName() %]_WordSelected_"]').val(0);
        for (var i = 0; i < highlightedWords.length; i++) {
            $('#[% QuestionName() %]_Highlight' + (i + 1)).val($('#[% QuestionName() %]_Text .highlightingSpan[data-word=' + highlightedWords[i] + ']').text());
            $('#[% QuestionName() %]_WordSelected_' + highlightedWords[i]).val(1);
    var highlightedWords = JSON.parse($('#[% QuestionName() %]_MasterData').val() || '[]');
    // Select / Deselect    
    $('#[% QuestionName() %]_Text .highlightingSpan').click(function(){
        // Selecting
        if (!$(this).hasClass('highlighted')) {
            var highlightedWord = Number($(this).data('word'));
            highlightedWords.sort(function(a, b) { return a - b; });
        // Deselecting
        else {
            var highlightedWord = Number($(this).data('word'));
            highlightedWords.splice(highlightedWords.indexOf(highlightedWord), 1);
    // Reset all
    $('#[% QuestionName() %]_ResetAllHighlighting').click(function(){
        $('#[% QuestionName() %]_Text .highlighted').removeClass('highlighted');
        $('#[% QuestionName() %]_MasterData').val('[]');
        $('#[% QuestionName() %]_HighlightCount').val('0');
        $('#[% QuestionName() %]_div .highlightInput').val('');
        $('[id^="[% QuestionName() %]_WordSelected_"]').val(0);

On the next page, we'll need to create a collection of quota questions, one for each word.  The cell limit can be set to 99999 or similar.  Each quota question needs one quota cell with this qualification logic:

HighlightingWords_WordSelected_X = 1

"HighlightingWords" being the name of the free format question and "X" being the current word we want to count with this quota question.
answered Apr 8 by Zachary Platinum Sawtooth Software, Inc. (171,950 points)
selected Apr 13 by Quentin
Thanks Zachary!  I'll give this a try.
Thanks again Zachary!  I just tried it out and it seems to be working.