Check out the LimeSurvey source code on GitHub!
Welcome, Guest
Username: Password:

TOPIC: fill ranking array with answers from previous question

fill ranking array with answers from previous question 5 years 3 months ago #59432

Hello,

I'm having a ranking question and I'm trying to build an array list or label set from answers from a previous question (label set).

Is this possible in LimeSurvey?

Jan Willem de Lange
The administrator has disabled public write access.

fill ranking array with answers from previous question 5 years 3 months ago #59434

  • lsexton
  • lsexton's Avatar
  • Offline
  • Fresh Lemon
  • Posts: 8
  • Karma: 0
Hi there,

I'm trying to do something similar, where the list of the items to rank is to be built from a 5-point scale array, but only if they mention punches 1-4 for any of the items in the array (i.e. if they mention punch 5, the option shouldn't exist in the ranking question).

Is there a simple workaround for this? Thanks for the help!

Luke
The administrator has disabled public write access.

fill ranking array with answers from previous question 5 years 3 months ago #59455

  • lsexton
  • lsexton's Avatar
  • Offline
  • Fresh Lemon
  • Posts: 8
  • Karma: 0
Hi again,

Let me provide some additional information:

Limesurvey version is 1.86

I am trying to build the list of items to rank based on the respondents answer to the previous question.

The previous question is an array (flexible labels) type, using a 5-point scale.

The question I'm trying to modify is a Ranking type question. I only want to respondent able to rank those that they rated 1-4 in the previous question, and to not display those they rated 5.

I have set-up the javascript requirements and have javascript working on some previous questions (to hide responses based on selections etc).

Any help will be greatly appreciated!

Thanks!
The administrator has disabled public write access.

fill ranking array with answers from previous question 5 years 3 months ago #59487

  • tpartner
  • tpartner's Avatar
  • Offline
  • LimeSurvey Team
  • Posts: 6122
  • Thank you received: 1357
  • Karma: 533
Jan, I have created a workaround to filter a ranking question that may meet your requirements. The workaround can be applied to filter and ranking on the same page or on separate pages as seen in this Demo.

Luke, we can use the two-page method for your problem. We just need to place your array on page 1 with the filter question and then add a small script to auto-check the appropriate options of the filter question and hide it. I'll get back to you with a script.
Cheers,
Tony Partner

Solutions, code and workarounds presented in these forums are given without any warranty, implied or otherwise.
The administrator has disabled public write access.

fill ranking array with answers from previous question 5 years 3 months ago #59489

Hello Tony,

Looks good!! The ranking I'm building is based on a matrix:
- item 1: yes, no, sometimes
- item 2: yes, no, sometimes

Only the yes and the sometimes items should appear in the ranking. I'm gone give it a try with your script.

Many thanks,
Jan Willem
The administrator has disabled public write access.

fill ranking array with answers from previous question 5 years 3 months ago #59491

  • tpartner
  • tpartner's Avatar
  • Offline
  • LimeSurvey Team
  • Posts: 6122
  • Thank you received: 1357
  • Karma: 533
Ah, that sounds exactly like what Luke is trying - "filter a ranking question by specific inputs in an array".
Cheers,
Tony Partner

Solutions, code and workarounds presented in these forums are given without any warranty, implied or otherwise.
The administrator has disabled public write access.

fill ranking array with answers from previous question 5 years 3 months ago #59504

  • lsexton
  • lsexton's Avatar
  • Offline
  • Fresh Lemon
  • Posts: 8
  • Karma: 0
Thanks for the help Tony - look forward to seeing the script

Cheers,
Luke
The administrator has disabled public write access.

fill ranking array with answers from previous question 5 years 3 months ago #59505

  • tpartner
  • tpartner's Avatar
  • Offline
  • LimeSurvey Team
  • Posts: 6122
  • Thank you received: 1357
  • Karma: 533
Luke, I can't remember - does array filter work with two multiple-options in 1.86? In other words, can one multiple-options filter another?
Cheers,
Tony Partner

Solutions, code and workarounds presented in these forums are given without any warranty, implied or otherwise.
The administrator has disabled public write access.

fill ranking array with answers from previous question 5 years 3 months ago #59506

  • lsexton
  • lsexton's Avatar
  • Offline
  • Fresh Lemon
  • Posts: 8
  • Karma: 0
Not sure Tony - I'll set something up and test it.

Cheers,
Luke
The administrator has disabled public write access.

fill ranking array with answers from previous question 5 years 3 months ago #59507

  • lsexton
  • lsexton's Avatar
  • Offline
  • Fresh Lemon
  • Posts: 8
  • Karma: 0
Hi Tony, array_filter doesn't appear as an option under Question Attributes for a multiple options question type in 1.86.



Cheers,
Luke
The administrator has disabled public write access.

fill ranking array with answers from previous question 5 years 3 months ago #59508

  • tpartner
  • tpartner's Avatar
  • Offline
  • LimeSurvey Team
  • Posts: 6122
  • Thank you received: 1357
  • Karma: 533
Hmm...bummer...is updating to 1.90 an option?
Cheers,
Tony Partner

Solutions, code and workarounds presented in these forums are given without any warranty, implied or otherwise.
The administrator has disabled public write access.

fill ranking array with answers from previous question 5 years 3 months ago #59509

  • lsexton
  • lsexton's Avatar
  • Offline
  • Fresh Lemon
  • Posts: 8
  • Karma: 0
Hi Tony - not with this survey unfortunately ...
The administrator has disabled public write access.

fill ranking array with answers from previous question 5 years 3 months ago #59510

  • tpartner
  • tpartner's Avatar
  • Offline
  • LimeSurvey Team
  • Posts: 6122
  • Thank you received: 1357
  • Karma: 533
Okay, lemme give it some thought - stand by.
Cheers,
Tony Partner

Solutions, code and workarounds presented in these forums are given without any warranty, implied or otherwise.
The administrator has disabled public write access.

fill ranking array with answers from previous question 5 years 3 months ago #59566

  • tpartner
  • tpartner's Avatar
  • Offline
  • LimeSurvey Team
  • Posts: 6122
  • Thank you received: 1357
  • Karma: 533
Jan, we can meet your requirements by using the workaround mentioned above with a little extra JS to automatically trigger the checking of a multiple options question if a radio in column 1 or 3 of an array is checked.

1) Add the rankFilter function from the workaround to your template.js file.

2) On page 1, create your array question and a multiple options question (we'll hide the multiple options with JavaScript). Both questions must have identical sub-questions and sub-question codes.

3) Place the following script in the source of one of the questions on page 1. Replace "AA" (line 7) with the question ID of the array question and "MM" (line 7) with the question ID of the multiple options question. The "[1,3]" param dictates which columns of the array will trigger checking the multi-options. This script hides the multi-options question and interrupts the next/submit function to automatically check the appropriate box in the multi-options for all radios checked in columns 1 and 3 of the array.
<script type="text/javascript" charset="utf-8">
 
	$(document).ready(function() {
 
		// Call the function
		// Params = Array ID, Hidden Multi-opt ID, "Trigger" columns (in square brackets, separated by comma)
		triggerCells(AA, MM, [1,3]);
 
		function triggerCells(q1ID, qHiddenID, columns) {
 
			// Add a class to all array cells in "trigger" columns
			$(columns).each(function(i) {
				var colIndex = (this-1);
				$('#question'+q1ID+' table.question tbody').each(function() {
					$('td:eq('+colIndex+')', this).addClass('trigger');
				});
			});
 
			// Hide the hidden question
			$('#question'+qHiddenID+'').hide();
 
			// Find the survey and group IDs
			if($('input#fieldnames').length != 0) {
				var fieldNames = $('input#fieldnames').attr('value');
				var tmp = fieldNames.split('X');
				var sID = tmp[0];
				var gID = tmp[1];
			}
 
			// Interrupt next/submit function 
			$('form#limesurvey').submit(function(){
				// Clear the hidden question
				$('#question'+qHiddenID+' li .checkbox').attr('checked', false);
 
				// Loop through all rows of the array and if a "trigger" cell is checked, check the corresponding box in the hidden question
				$('#question'+q1ID+' table.question tbody').each(function(i) {
					if($('.trigger .radio:checked', this).length > 0) {
						$('#question'+qHiddenID+' li:eq('+i+') .checkbox').attr('checked', true);
					}
				});
 
				return true;
			});
		}
 
	});
 
</script>

4) On page 2, Create a multiple options question and the ranking question (we'll hide the multiple options with JavaScript). These questions also need to have identical sub-questions and sub-question codes as those on page 1.

5) Set the multiple options on page 2 to be filtered by the multiple options on page 1.

6) Place the following script in the source of one of the questions on page 2. Replace "MM" with the ID of the multiple options question and "RR" with the ID of the ranking question. Do not modify the "1". This calls the rankFilter function which hides all choices in the ranking question except those checked in the page 1 multi-options.
<script type="text/javascript" charset="utf-8">
 
	$(document).ready(function() {
 
		rankFilter(MM, RR, 1);
	});
 
</script>
Cheers,
Tony Partner

Solutions, code and workarounds presented in these forums are given without any warranty, implied or otherwise.
The administrator has disabled public write access.

fill ranking array with answers from previous question 5 years 3 months ago #59569

  • tpartner
  • tpartner's Avatar
  • Offline
  • LimeSurvey Team
  • Posts: 6122
  • Thank you received: 1357
  • Karma: 533
Luke, due to your somewhat aged LS version, we can do something similar to Jan's solution but will need to pass the sub-question codes and values to page 2 via a couple of hidden short-texts and a hidden boilerplate question. We'll also need to modify the functions slightly to handle the different method of passing data.

1) Add the following variation of the workaround function to your template.js file:
// A function to filter choices in a ranking question
function rankFilter2(q1ID, q2ID) {	
 
	// Hide the boilerplate
	$('#question'+q1ID+'').hide();
 
	// Find the survey and group IDs
	if($( 'input#fieldnames' ).length != 0) {
		var fieldNames = $( 'input#fieldnames' ).attr('value');
		var tmp = fieldNames.split('X');
		var sID = tmp[0];
		var gID = tmp[1];
	}
 
	// Handle the option codes and text passed from page 1
	var triggers = $('#question'+q1ID+' .triggers').text().split(',');
	var nonTriggers = $('#question'+q1ID+' .nonTriggers').text().split(',');
 
	$(triggers).each(function(i) {			
		// Split out the answer code and value
		var tmp2 = this.split('|*|');
		var ansCode = tmp2[0];
		var ansTxt =  tmp2[1];
 
		// If option is checked and not in rank choices or output, add it to the rank choices
		if($('#question'+q2ID+' select.select option[value="'+ansCode+'"]').length == 0 && $('#question'+q2ID+' .output input[id^="fvalue_"][value="'+ansCode+'"]').length == 0) {
			$('<option value="'+ansCode+'">'+ansTxt+'</option>').appendTo('#question'+q2ID+' select.select');
		}
	});
 
	$(nonTriggers).each(function(i) {			
		// Split out the answer code and value
		var tmp2 = this.split('|*|');
		var ansCode = tmp2[0];
		var ansTxt =  tmp2[1];
 
		// Remove it from the rank choices
		$('#question'+q2ID+' select.select option[value="'+ansCode+'"]').remove();
		// Remove it from the rank output and reset hidden values
		$('#question'+q2ID+' .output input[id^="fvalue_"][value="'+ansCode+'"]').attr('value', '').siblings('input.text').val('').siblings('img').hide();
	});
 
	// Clean up empty inputs in the rank output table
	$('#question'+q2ID+' .output table tr').each(function(i) {
		var nextRow = $(this).next('tr');
		if($('input.text', this).val() == '' && $('input.text', nextRow).val() != '') {
			$('input.text', this).val($('input.text', nextRow).val());
			$('input.text', nextRow).val('');
			$('input[id^="fvalue_"]', this).attr('value', $('input[id^="fvalue_"]', nextRow).attr('value'));
			$('input[id^="fvalue_"]', nextRow).attr('value', '');
		}
	});
 
	// Show the scissors for the last populated rank output row
	$('#question'+q2ID+' .output table img[id^="cut_"]').hide();
	$('#question'+q2ID+' .output table input.text[value!=""]:last').siblings('img[id^="cut_"]').show();
 
	// Hide extra rank output rows
	var optNum = $(triggers).length;
	$('#question'+q2ID+' .output table tr').hide();
	$('#question'+q2ID+' .output table tr:lt('+(optNum+1)+')').show();
 
	maxAnswersFix();
 
	// A listener to work around the built in max-answers function
	$('#question'+q2ID+' td.rank').click(function (event) {
		maxAnswersFix();
	});
 
	// A work around for the built in max-answers function
	function maxAnswersFix() { 
		$('#question'+q2ID+' select.select').attr('disabled', true);
		$('#question'+q2ID+' td.output tr:visible').each(function(i) {
			if($('input.text', this).val() == '') {
				$('#question'+q2ID+' select.select').attr('disabled', false);
			}
		});
	}
}

2) On page 1, create your array question and two short text questions (we'll hide the short texts with JavaScript).

3) Place the following script in the source of one of the questions on page 1. Replace "AA" (line 7) with the question ID of the array question, "HH1" and "HH2" (line 7) with the question IDs of the short-text questions. The "[1,2,3,4]" param dictates which columns of the array will load "triggers". This script hides the short-text questions and interrupts the next/submit function to load the first short-text with codes and values of subquestions to show in the ranking (triggers) and loads the second short-text with the ones to remove/hide (non-triggers).
<script type="text/javascript" charset="utf-8">
 
	$(document).ready(function() {
 
		// Call the function
		// Params = Array ID, Hidden Multi-opt ID, "Trigger" columns (in square brackets, separated by comma)
		storeTriggers(AA, HH1, HH2, [1,2,3,4]);
 
		function storeTriggers(q1ID, qHidden1ID, qHidden2ID, columns) {
 
			// Add a class to all array cells in "trigger" columns
			$(columns).each(function(i) {
				var colIndex = (this-1);
				$('#question'+q1ID+' table.question tbody').each(function() {
					$('td:eq('+colIndex+')', this).addClass('trigger');
				});
			});
 
			// Hide the hidden questions
			$('#question'+qHidden1ID+'').hide();
			$('#question'+qHidden2ID+'').hide();
 
			// Find the survey and group IDs
			if($('input#fieldnames').length != 0) {
				var fieldNames = $('input#fieldnames').attr('value');
				var tmp = fieldNames.split('X');
				var sID = tmp[0];
				var gID = tmp[1];
			}
 
			// Interrupt next/submit function 
			$('form#limesurvey').submit(function(){
 
				var triggers = new Array();
				var nonTriggers = new Array();
 
				// Loop through all rows of the array build an array of the "trigger" codes and text
				$('#question'+q1ID+' table.question tbody').each(function(i) {
					var optTxt = $('th', this).text();
					var optTmp = $(this).attr('id').split('X'+gID+'X'+q1ID+'');
					var optCode = optTmp[1];
					var optString = optCode+'|*|'+optTxt;
					if($('.trigger .radio:checked', this).length > 0) {
						triggers.push(optString);
					}
					else {
						nonTriggers.push(optString);
					}
				});
 
				// Populate the hidden questions
				$('#question'+qHidden1ID+' input.text').val(triggers);
				$('#question'+qHidden2ID+' input.text').val(nonTriggers);
 
				return true;
			});
		}
 
	});
 
</script>

4) On page 2, Create a boilerplate question and the ranking question (we'll hide the boilerplate with JavaScript). The ranking question must have identical sub-questions and sub-question codes as the array on page 1.

5) For the boilerplate text, use two {INSERTANS} tags to pipe in the answer from the page 1 short-text questions and wrap them in <span> elements with classes "trigger" and "nonTriggers". So the source of the boilerplate should look something like (with correct IDs, of course):
<span class="triggers">{INSERTANS:11111X22X3}</span><span class="nonTriggers">{INSERTANS:11111X22X4}</span>

6) Place the following script in the source of one of the questions on page 2. Replace "BB" with the ID of the boilerplate question and "RR" with the ID of the ranking question. This calls the rankFilter2 function which hides all choices in the ranking question except those passed from page 1 as "triggers".
<script type="text/javascript" charset="utf-8">
 
	$(document).ready(function() {
 
		rankFilter2(BB, RR);
	});
 
</script>
Cheers,
Tony Partner

Solutions, code and workarounds presented in these forums are given without any warranty, implied or otherwise.
Last Edit: 5 years 3 months ago by tpartner.
The administrator has disabled public write access.
Moderators: ITEd
Time to create page: 0.319 seconds
Imprint                   Data Protection Statement                  Revocation information and revocation form