Welcome to the LimeSurvey Community Forum

Ask the community, share ideas, and connect with other LimeSurvey users!

Storing a value from JavaScript as an answer to a question.

More
1 hour 59 minutes ago #274071 by banffboss
Please help us help you and fill where relevant:
Your LimeSurvey version: 6.16.4
==================

I am trying to store the value of a JavaScript as an answer to a question. 
Task: I want to randomize the order of a list (radio) question AND save the order in which it was randomized.
Idea: Use JavaScript to visually randomize the order of answers in question Q1, scan the DOM for the order and save the order (eg. A02, A03, A01) as an answer to the hidden question Q1order. 

Script:
Code:
(function () {
    console.log('script started');
 
    var qid = {QID};
    console.log('qid:', qid);
 
    var question = document.getElementById('question' + qid);
    console.log('question:', question);
 
    if (!question) {
        console.log('Question container not found');
        return;
    }
 
    if (question.dataset.orderRandomized === 'true') {
        console.log('Already randomized');
        return;
    }
    question.dataset.orderRandomized = 'true';
 
    function shuffle(array) {
        for (var i = array.length - 1; i > 0; i--) {
            var j = Math.floor(Math.random() * (i + 1));
            var temp = array[i];
            array[i] = array[j];
            array[j] = temp;
        }
        return array;
    }
 
    var items = question.querySelectorAll('ul.answers-list > li.answer-item, table.question tbody tr.answer-item');
    console.log('items found:', items.length);
 
    if (!items.length) {
        console.log('No answer items found');
        return;
    }
 
    var normalItems = [];
    var fixedItems = [];
 
    for (var k = 0; k < items.length; k++) {
        var item = items[k];
        var input = item.querySelector('input[type="radio"], input[type="checkbox"]');
        var code = input ? input.value : null;
 
        console.log('code:', code);
 
        if (code === 'OTHER' || code === 'NONE' || code === 'AO06') {
            fixedItems.push(item);
        } else {
            normalItems.push(item);
        }
    }
 
    shuffle(normalItems);
 
    var finalItems = normalItems.concat(fixedItems);
 
    var containerUl = question.querySelector('ul.answers-list');
    var containerTbody = question.querySelector('table.question tbody');
    var container = containerUl || containerTbody;
 
    console.log('container:', container);
 
    if (!container) {
        console.log('No answer container found');
        return;
    }
 
    for (var m = 0; m < finalItems.length; m++) {
        container.appendChild(finalItems[m]);
    }
 
    var orderCodes = [];
    for (var n = 0; n < finalItems.length; n++) {
        var input2 = finalItems[n].querySelector('input[type="radio"], input[type="checkbox"]');
        if (input2 &amp;&amp; input2.value) {
            orderCodes.push(input2.value);
        }
    }
 
    console.log('final order:', orderCodes);
 
    var all = document.querySelectorAll('input, textarea');
    var hiddenField = document.querySelector('[id*="{Q1order.sgqa}"]') || document.querySelector('[name*="{Q1order.sgqa}"]');
    if (!hiddenField) {
    console.log('Hidden field not found');
    return;
    }
    console.log('hiddenField:', hiddenField);
 
    if (!hiddenField) {
        console.log('Hidden field not found');
        return;
    }
 
    hiddenField.value = orderCodes.join('|');
    hiddenField.dispatchEvent(new Event('input', { bubbles: true }));
    hiddenField.dispatchEvent(new Event('change', { bubbles: true }));
 
    console.log('Saved order:', hiddenField.value);
    console.log(document.querySelectorAll('input'));
})();

When I check the console, I can see that the values for hiddenField are correct.

I set up a question Q1order (equation question), left the question text empty and used Q1order as the equation.
I created a question Q1Debug (equation question), question text: "Show Order: {Q1Debug}" and used Q1order as the equation.

My Problem: The value that should be in Q1order (the order of the question) is not shown in Q1Debug. Do I have to use a variant of Q1order.show ?

I tried: Using Q1 and Q1order/Q1Debug on different pages (I am using show questions by group), tried to use it in the preview mode and in an activated survey. I am pretty sure the order is calculated in the right way, I just dont know how to to get it "out of the script" into the visible part of Limesurvey.

I am quite new to using scripts in limesurvey and I am a bit confused between the difference of curly brackets in the question text, equation text and general use of the expression script.

Please Log in to join the conversation.

More
1 hour 55 minutes ago #274072 by flevin_keller
Hey, I think your script is actually fine, the way you’re collecting and setting the order looks correct.

From what I’ve seen with LimeSurvey, the issue is usually not the JS part but how it handles values internally. Even if the value is set correctly in the hidden field (like you’re seeing in the console), it doesn’t always show up in equation questions right away.

I ran into something similar before, and it was basically a sync issue between JS and ExpressionScript.

You could try a couple of small things:

using a normal short text question instead of an equation one for storing the value
or placing the questions on separate pages so LimeSurvey re-evaluates everything

Sometimes it just needs that extra trigger to “recognize” the value.

Your approach overall looks good though, you’re definitely on the right track.

Please Log in to join the conversation.

More
1 hour 15 minutes ago #274073 by tpartner
If you search the forums, you should find many examples of storing the randomization order.

I have not fully debugged your script, but you cannot programmatically load equation type questions. You will need to load your values into a hidden (via JS or CSS) text question. If you need ExpressionScript to recognize those loaded/updated values before submitting the page, fire a .change() event on the text input.

Cheers,
Tony Partner

Solutions, code and workarounds presented in these forums are given without any warranty, implied or otherwise.

Please Log in to join the conversation.

More
53 minutes ago #274074 by Joffm
tpartner was faster than I.

And Yes

If you search the forums, you should find many examples of storing the randomization order.

Store the random order in a (hidden) question of type "short text" with this script
Code:
<script type="text/javascript" charset="utf-8">
    $(document).on('ready pjax:scriptcomplete',function(){
        
        //Identify the questions
        var thisQuestion = $('#question{QID}');
        var hiddenQuestion = $(thisQuestion).nextAll('.text-short:eq(0)');
        
        // Create an array of answer codes
        var answerCodes = [];
        $('li.answer-item', thisQuestion).each(function(i) {
            answerCodes.push($(this).attr('id').split('X{QID}')[1]);
        });
        
        // Load the hidden question
        $('input:text', hiddenQuestion).val(answerCodes);        
    });
</script>


And then you can use this in other questions, other question types to show the same order.
 
You may send a lss export of a prototype.

Joffm

Volunteers are not paid.
Not because they are worthless, but because they are priceless

Please Log in to join the conversation.

More
49 minutes ago - 40 minutes ago #274075 by banffboss

If you search the forums, you should find many examples of storing the randomization order.

I have not fully debugged your script, but you cannot programmatically load equation type questions. You will need to load your values into a hidden (via JS or CSS) text question. If you need ExpressionScript to recognize those loaded/updated values before submitting the page, fire a .change() event on the text input.



 
Thank you guys very much! I am currently using the script Joffm provided and it is working so far. I will use it to dive deeper into what I want to do! Thank you so much!

Whats the difference between using the script in the question field and/or using the script field?
Last edit: 40 minutes ago by banffboss.

Please Log in to join the conversation.

More
20 minutes ago #274076 by tpartner

Whats the difference between using the script in the question field and/or using the script field?
None, except in the script field you don't wrap it in a <script> tag.

(I never understood the need for the script field)

Cheers,
Tony Partner

Solutions, code and workarounds presented in these forums are given without any warranty, implied or otherwise.

Please Log in to join the conversation.

Moderators: tpartnerholch

Lime-years ahead

Online-surveys for every purse and purpose