Ranking questions are a powerful tool in survey research that allow researchers to gather valuable insights into individuals’ preferences, priorities, and perceptions.
For ranking, we have the following cases:
- Regular Ranking
- Ranking with min and max
- Ranking with array filter from user-answered questions
- Ranking from a recode question array filtered
Case 1 Regular Ranking
For regular ranking you just need to add the following JS code to a Multiple Text question:
Use the code below, just edit the question code to the one you use.
//Ranking
/*STARTS EDITABLE PART - Change call to function to correct one*/
let questionCode = "Q1"; //Change to current question code
/* ENDS EDITABLE PART*/
let scripts = ["https://synocdn.com/js/survey/library/ranking.js"];
let numberOfElements = $('.form-control').length;
let promises = scripts.map((script) => {
return new Promise((resolve, reject) => {
document.querySelector("body").style.opacity = "0";
let s = document.createElement("script");
s.src = script;
s.onload = resolve;
s.onerror = reject;
document.head.appendChild(s);
});
});
Promise.all(promises)
.then(() => {
ranking({
question_code: questionCode,
validation: {
n_required: numberOfElements
}
});
document.querySelector("body").style.opacity = "1";
})
.catch((error) => {
console.error(`Failed to load script: ${error}`);
});
The result will be as follow:
Case 2 Ranking with min and max
As in case 1, first add a multiple text question as the example below.
Then copy the JS code below, adjust as needed.
//Ranking
/*STARTS EDITABLE PART - Change call to function to correct one*/
let questionCode = "Q2"; //Change to current question code
let minValue = 1; //Change to desire min number
let maxValue = 3; //Change to desire max number
/* ENDS EDITABLE PART*/
let scripts = ["https://synocdn.com/js/survey/library/ranking.js"];
let promises = scripts.map((script) => {
return new Promise((resolve, reject) => {
document.querySelector("body").style.opacity = "0";
let s = document.createElement("script");
s.src = script;
s.onload = resolve;
s.onerror = reject;
document.head.appendChild(s);
});
});
Promise.all(promises)
.then(() => {
ranking({
question_code: questionCode,
validation: {
min_limit : minValue,
max_limit : maxValue
}
});
document.querySelector("body").style.opacity = "1";
})
.catch((error) => {
console.error(`Failed to load script: ${error}`);
});
You will get a result like the following:
Case 3 Ranking with array filter from user-answered questions
For this case, we will need to do 2 steps
- Add a SCHEMA to the original question, the one from which we are getting the randomization.
- Add the JS to the question that will received the array filtering.
For this, you will need to add the following JS to the original question to add the SCHEMA.
/* START EDITING PART */
let questionSchema = "Q3xSCHEMA"; // Create a new open text question and set the question code as "QuestionCode"xSCHEMA
const typeOfQuestion = "checkbox" //Use checkbox for multiple and radio for single
/* ENDS EDITING PART */
function setSCHEMA(questionSchema) {
const checkboxesInput = document.querySelectorAll(`.form-check input[type="${typeOfQuestion}"]`);
const checkboxesValues = Array.from(checkboxesInput).map(checkbox => checkbox.value).join(',');
document.querySelector('.form-control').value = checkboxesValues;
document.querySelector(`#q_${questionSchema}_card`).classList.add("d-none");
}
setSCHEMA(questionSchema);
The same options will be passed over to the next question.
Now add this JS to the desired questions, and edit the needed parts.
//Ranking
/*STARTS EDITABLE PART - Change call to function to correct one*/
let questionCode = "Q4"; //Change to current question code
let filterQuestion = "Q3"; // Change to current question code of the filter
let filterSchema = "Q3xSCHEMA"; // Change to current question code of filter's schema
let filterType = "inclusive"; // If inclusive, keeps the selected options in filter, if exclusive, will exclude selected in filter Answer options that didn't appeared in filter_schema are ignored for array filter process
/* ENDS EDITABLE PART*/
let maxValue = response.answers.filter(elem => elem.questionCode === filterQuestion).map(elem => elem.label).length;
let scripts = ["https://synocdn.com/js/survey/library/ranking.js"];
let promises = scripts.map((script) => {
return new Promise((resolve, reject) => {
document.querySelector("body").style.opacity = "0";
let s = document.createElement("script");
s.src = script;
s.onload = resolve;
s.onerror = reject;
document.head.appendChild(s);
});
});
Promise.all(promises)
.then(() => {
ranking({
question_code: questionCode,
array_filter: {
filter: filterQuestion,
filter_schema: filterSchema,
type: filterType
},
validation: {
min_limit: maxValue, //It forces to rank all shown options
}
});
document.querySelector("body").style.opacity = "1";
})
.catch((error) => {
console.error(`Failed to load script: ${error}`);
});
After this, you will get the desired result:
Case 4 Ranking from a recode question array filtered
Array filtering is an essential part of many surveys, with this we can make sure respondents answer only relevant options.
For this we will need to take 2 steps:
- Have a matrix question to later filter.
- Add a SCHEMA and the filtering code from matrix to multiple choice to the original question, the one from which we are getting the randomization.
- Add JS to the desired question while adjusting the code.
For this example, we will pass the options with values from 4 to 5, we will received the options from below that fulfill the conditions.
After that we need to use a multiple choice question
with JS that will work as a hidden filter, remember that when going live to change the value of const test = true;
to const test = false;
Copy and edit the JS code as neeeded.
/* START EDITING PART */
const question_code = "Q5"; // Question code of the question wanted to filter
const columns = [4,5]; // Array of columns wanted, could be just one: [1], or many: [1, 2, 3]
const test = true; // set this true if you are testing, this will show the filter, set it as false and it will hide it
/* ENDS EDITING PART */
const checkboxes = document.querySelectorAll(".form-check input");
if (response.answers.some(question => question.questionCode === question_code)) {
if (!response.answers.some(question => question.questionCode === question_code && columns.includes(Number(question.columnCode)))) {
checkboxes[checkboxes.length -1].checked = true;
} else {
let checky = Array.from(response.answers.filter(question => question.questionCode === question_code && columns.includes(Number(question.columnCode)))).map(item => Number(item.rowCode) - 1);
checky.forEach(check => {
checkboxes[check].checked = true;
});
}
} else {
alert(`${question_code} question was not found`);
}
const checkboxesInput = document.querySelectorAll('.form-check input[type="checkbox"]');
const checkboxesValues = Array.from(checkboxesInput).map(checkbox => checkbox.value).join(',');
document.querySelector('.form-control').value = checkboxesValues;
if(!test){
document.querySelector("body").classList.add("d-none");
document.querySelector("#p_next").click();
}
Based on the example, you will get these options.
Now we will need to add the following JS to the question that will be filtered:
//Ranking
/*STARTS EDITABLE PART - Change call to function to correct one*/
let questionCode = "Q7"; //Change to current question code
let filterQuestion = "Q6"; // Change to current question code of the filter
let filterSchema = "Q6xSCHEMA"; // Change to current question code of filter's schema
let filterType = "inclusive"; // If inclusive, keeps the selected options in filter, if exclusive, will exclude selected in filter Answer options that didn't appeared in filter_schema are ignored for array filter process
/* ENDS EDITABLE PART*/
let maxValue = response.answers.filter(elem => elem.questionCode === filterQuestion).map(elem => elem.label).length;
let scripts = ["https://synocdn.com/js/survey/library/ranking.js"];
let promises = scripts.map((script) => {
return new Promise((resolve, reject) => {
document.querySelector("body").style.opacity = "0";
let s = document.createElement("script");
s.src = script;
s.onload = resolve;
s.onerror = reject;
document.head.appendChild(s);
});
});
Promise.all(promises)
.then(() => {
ranking({
question_code: questionCode,
array_filter: {
filter: filterQuestion,
filter_schema: filterSchema,
type: filterType
},
validation: {
min_limit: maxValue, //It forces to rank all shown options
}
});
document.querySelector("body").style.opacity = "1";
})
.catch((error) => {
console.error(`Failed to load script: ${error}`);
});
With this you will get the following result.
You can see the complete flow here: