In the syntax below, s1 and s2 represents instances of set objects or form objects (returned from the f function). For add and remove s1 represents only an instance of the set object, because these methods are not defined for form objects.
inc
s
1.inc(code)inc returns true if the code is contained in the set s1.
For example, for a multi question q1, the expression
f("q1").inc("1")is true if the answer with code "1" has been selected on q1.
If you need an expression that is true if the answer with code "1" or the answer with code "2" has been selected, you can use this code:
f("q1").inc("1") || f("q1").inc("2")If you need an expression that is true if the answer with code "1" and the answer with code "2" has been selected, you can use this code:
f("q1").inc("1") && f("q1").inc("2")
size
s
1.size()size returns the number of elements in the set s1.
Asking for Favorite Only when More than 1 Item is Chosen
If you have a multi question cars asking for cars the respondent would like to drive, followed by a single question cars_favorite asking for the favorite among those selected in cars, the single question is only needed when more than 1 element is chosen on the multi. This can be achieved with the following expression in a condition:
f("cars").size()>1The cars favorite question will then have the following code mask so that it only shows answers from the cars question::
f("cars")
union isect and diff
There are three methods available to use for set operations: union, isect and diff. These methods are useful when you need complex code masks, for example when you want to filter the answer list based on answers to two previous questions. Examples of this are: Showing the items answered on both questions, on any of the questions, on one but not the other etc.
s
1.union(s2)The union of two sets s1 and s2 is the set obtained by combining the members of both sets. So union will return a set consisting of all elements in s1or s2.
Figure 1 - Set Example 1
s1.union(s2)
s
1.isect(s2)The intersection of two sets s1 and s2 is the set of elements common to s1 and s2. So isect will return a set consisting of the elements that are both in s1and s2.
Figure 2 - Set Example 2
s1.isect(s2)
s
1.diff(s2)
The difference between two sets s1 and s2 will yield a set consisting of the elements that are in the first set, but not in the other. For difference the order of the sets in the expression is significant. s1.diff(s2) will return a set consisting of the elements in s1 that are not in s2, but s2.diff(s1) will return a set consisting of the elements in s2 that are not in s1. As the illustrations show, these are two completely different sets.
Figure 3 - Set Example 3
s1.diff(s2)Figure 4 - Set Example 4
s2.diff(s1)
Filtering an Answer List on Items Selected in Two Previous Questions
You have two multi questions q1 and q2, and then a loop where you loop through the same answer list that is used in q1 and q2.
If you want the loop to be filtered so that only the items the respondent answered in both q1 and q2, you can use a code mask like this on the loop:
f("q1").isect(f("q2"))If you want the loop to be filtered so that all the items the respondent answered in either of q1 or q2, you can use a code mask like this on the loop:
f("q1").union(f("q2"))If you want the loop to be filtered so that only items answered in q1, but not in q2, you can use a code mask like this:
f("q1").diff(f("q2"))Similar, for items answered in q2 but not in q1:
f("q2").diff(f("q1"))
Filtering Answers Not Selected in a Previous Question
If you have a multi question q1 followed by a grid q2 where you only want the answers not selected in q1 to be displayed, you can use the a function to get a set with all the codes in the answer list, and use the diff method to remove the codes of the answers selected on q1. The code for such a code mask will be like this:
a("q2").diff(f("q1"))You have to use the same codes for corresponding items in the answer lists of the two questions. This can easily be achieved for example by using a predefined list.
Always Including a "Don't know" Answer Alternative
Often you want to filter the answer list, but you want a "Don't know" alternative always to be included at the bottom of the answer list. Say for example a multi q1 is followed by a single question q3 where the answers given to q1 and "Don't know" should be displayed. It is a good idea to assign a code to "Don't know" that is different from the other codes, for example by using a large number like "99" or letters like "DK". We will use "DK" in this example. In the code mask of q3 we can use this code:
f("q1").union(set("DK"))
members
s
1.members()members is used to convert a set to an array.
Validating "Other, specify" in a 3D Grid
For grids/singles/multiples it is possible to automatically validate Other-specify by checking the "Other - Specify checking..." setting in Project Management > Survey Settings > Validation & XSS tab:
Figure 5 - "Other - Specify checking..." setting
However this setting does not apply to 3D grids since Forsta Plus cannot deduce which question within a 3D grid should be validated with the Other-specify; instead it is necessary to use some manual validation code.
The question ID to refer to an Other-specify within a 3D grid is:
3d-grid-id_code_otherFor example, we have a 3D grid (g1) containing a multi (q1) and a rating grid (q2); the 3d grid has answers/codes 1-4 with the 4th code being an Other specify.
Figure 6 - 3D Grid example using Other specify
We wish to validate so that the respondent is forced to add Other-specify text if they select this option in the multi q1. The validation code for this is:
var codes = a("q1").diff(set("97","98")).members();
if(f('q1').inc('4') && !f('g1_4_other').toBoolean() )
{
RaiseError();
SetQuestionErrorMessage(LangIDs.en,"Please specify in the Other Specify box");
}
if(!f('q1').inc('4') && f('g1_4_other').toBoolean())
{
RaiseError();
SetQuestionErrorMessage(LangIDs.en,"Please do not specify in the Other Specify box without selecting this answer");
}add and remove
To add and remove items from a set, there are two methods available: add and remove.
s
1.add(code);s1.remove(code);add will add code to the set s1. If code is already in the set s1, the set will not be changed. remove will remove code from the set s1. If code is not in the set s1, the set will not be changed.
These methods are not defined for the form objects (returned from the f function), only for the set object.
Using a Function to Filter an Answer List Based on the Answers on a Grid
If you have a grid where you give some elements a rating from 1-5, you may for example want the next question to use only the elements that get a score of 4 or 5. This can be achieved with a function like this defined in a script node:
function ScoreFilter(qID)
{
var form = f(qID);
var codes = form.domainValues();
var s = new Set();
var i : int;
for(i=0;i<codes.length;i++)
{
var code = codes[i];
if(form[code].get() == "4" || form[code].get() == "5")
{
s.add(code);
}
}
return s;
}
function ScoreFilter(qID) {
var form = f(qID);
var codes = form.domainValues();
var s = set();
for (var i = 0; i < codes.length; i++) {
var code = codes[i];
if (form.item(code).get() == "4" || form.item(code).get() == "5") {
s.add(code);
}
}
return s;
}
This function returns a set with the codes of the items that have received a score of "4" or "5". In the code mask where you want to use it , call this function with the question ID of the grid (for example q3) as argument:
ScoreFilter("q3")Note: If the respondent does not score any grid elements “4” or “5”, then ScoreFilter() will return an empty set/mask and the respondent will be presented with an empty question (since all answers are masked out). It would therefore be reasonable to also include a question mask (or condition node):ScoreFilter("q3").size()>0Then, if the question is ‘empty’, it will be skipped.
.any, .all and .none
These methods can be used to check whether a set includes specific codes:
s1.any(code1,code2,…,coden);s1.all(code1,code2,…,coden);s1.none(code1,code2,…,coden);any will return true if any of the codes listed can be found in the set s1.
all will return true if all of the codes listed can be found in the set s1.
none will return true if none of the codes listed can be found in the set s1.