v2022 Scripting Manual Rev1
v2022 Scripting Manual Rev1
This is revision 1 of the Forsta v2022 Scripting Manual published in January 2022. The information herein describes
Forsta Scripting and its features as of Build nr. 2022.1.23. New features may be introduced into the product after this
date. Go to www.forsta.com or check “News” on the Customer Extranet for the latest updates.
Copyright © 2022 by Forsta. All Rights Reserved.
This document is intended only for registered Forsta clients. No part of the contents of this document may be
reproduced or transmitted in any form or by any means without the written permission of Forsta.
Forsta makes no representations or warranties regarding the contents of this manual, and specifically disclaims any
implied warranties of merchantability or fitness for any particular purpose. The information in this manual is subject to
change without notice.
The companies, names and data used or described in the examples herein are fictitious.
- ii -
Forsta Confidential Forsta v2022 Scripting Manual
Table of Contents
Table of Contents ................................................................................................................................ 3
What's New in this Revision? ........................................................................................................... 14
1. Introduction..................................................................................................................................... 1
1.1. JScript .NET Fast Mode............................................................................................................. 1
1.1.1. All Variables Must Be Declared. .......................................................................................... 2
1.1.2. Functions Become Constants ............................................................................................. 2
1.1.3. The arguments Object is not Available ................................................................................ 2
1.1.4. Using a Sorting Function in the sort Method (on Array) ....................................................... 2
2. Where is Scripting Used in Forsta? .............................................................................................. 4
2.1. Conditions ................................................................................................................................... 4
2.2. Filtering Answer Lists, Scales and Loops .................................................................................. 5
2.2.1. Code Masks and Scale Masks ............................................................................................ 5
2.2.2. Column and Question Masks ............................................................................................... 7
2.3. Text Substitution/Response Piping ............................................................................................. 7
2.4. Validation Code .......................................................................................................................... 8
2.5. Script Nodes ............................................................................................................................. 10
2.6. Dynamic Questions.................................................................................................................. 11
2.7. Script Execution when Respondent Moves Backwards ........................................................... 12
2.8. The Syntax Highlighter ............................................................................................................. 12
2.8.1. Using the Syntax Highlighter ............................................................................................ 13
2.8.2. Syntax Highlighter Limitations........................................................................................... 14
3. Comments ...................................................................................................................................... 15
4. Types, Variables and Constants ................................................................................................. 16
4.1. Naming ..................................................................................................................................... 16
4.2. Data Declaration ...................................................................................................................... 16
4.3. Undefined Values .................................................................................................................... 17
4.4. Null .......................................................................................................................................... 17
4.5. Types ....................................................................................................................................... 19
4.5.1. Numeric ............................................................................................................................ 19
4.5.1.1. Integers ...................................................................................................................... 19
4.5.1.2. Floating-point Data .................................................................................................... 20
4.5.2. Boolean ............................................................................................................................. 21
4.5.3. Characters and Strings ...................................................................................................... 21
4.5.3.1. Unicode...................................................................................................................... 22
4.6. Conversion between Types/Conversion Functions ................................................................... 22
4.6.1. Conversion Methods in JScript .NET ................................................................................ 23
4.6.1.1. parseInt ....................................................................................................................... 23
4.6.1.2. parseFloat ................................................................................................................... 23
4.6.1.3. isNaN .......................................................................................................................... 24
4.6.1.4. isFinite ........................................................................................................................ 24
4.6.1.5. toString ....................................................................................................................... 24
4.6.1.6. valueOf ....................................................................................................................... 24
4.6.2. Conversion Methods in Forsta ........................................................................................... 24
4.6.2.1. toNumber .................................................................................................................... 24
4.6.2.2. toInt ............................................................................................................................. 24
- iii -
Forsta v2022 Scripting Manual Forsta Confidential
- iv -
Forsta Confidential Forsta v2022 Scripting Manual
-v-
Forsta v2022 Scripting Manual Forsta Confidential
- vi -
Forsta Confidential Forsta v2022 Scripting Manual
- vii -
Forsta v2022 Scripting Manual Forsta Confidential
- viii -
Forsta Confidential Forsta v2022 Scripting Manual
- ix -
Forsta v2022 Scripting Manual Forsta Confidential
-x-
Forsta Confidential Forsta v2022 Scripting Manual
- xi -
Forsta v2022 Scripting Manual Forsta Confidential
- xii -
Forsta Confidential Forsta v2022 Scripting Manual
- xiii -
Forsta v2022 Scripting Manual Forsta Confidential
Note: Only the latest changes to this documentation are listed here. Changes made to earlier revisions are
listed in the "Changes to the User Documentation" document which can be downloaded from the Forsta
Extranet at https://extranet.confirmit.com.
The following changes have been made since the last revision:
• The manual is updated with new logo, company and product names. Note that images will be updated at a
later date, and URLs, folder names etc. will be corrected as the changes become applicable.
• The SendPdfMail topic is updated (see SendPdfMail on page 154 for more information).
• The SendPdfMailWithCopy topic is updated (see SendPdfMailWithCopy on page 155 for more information).
• The QualityTerminate code example is added to the CintFulfillmentRespondentsTransition topic (see
CintFulfillmentRespondentsTransition on page 161 for more information).
• Appendix B is removed as it is no longer relevant.
Note: The general layout and language in this document is continually being corrected, adjusted and
improved to ensure the user has the best possible source of information. Only NEW information and details
of functionality that has changed since the previous revision are listed here - minor corrections to the text
and document layout are not listed.
Important!
We need your feedback so we can improve this document and provide you with the information you require. If
you have any comments or constructive criticism concerning the content or layout of this documentation,
please send an email to [email protected]. Please include in your email the section number and/or
heading text of the section to which your comment applies.
- xiv -
Forsta Confidential Forsta v2022 Scripting Manual
1. Introduction
Most Forsta surveys contain a quantity of script code. Scripts are used:
• In conditions, for controlling the flow through the questionnaire (skipping logic) and controlling whether or not
questions are to be displayed (question masks and column masks (in 3D grids)).
• For filtering the lists displayed in questions and the iterations in loops based on previous answers (code and
scale masks).
• In form elements for text substitution (response piping).
• For custom validation of user input.
• In general-purpose code contained in script nodes.
Forsta uses Microsoft’s JScript .NET scripting engine to evaluate all questionnaire expressions and to execute scripts.
The run-time environment of the interview engine supplies a number of functions and objects that provide references
to and let you manipulate survey variables. This documentation covers some of the fundamentals of JScript.NET and
the functions and objects provided by Forsta.
JScript.NET is not a condensed version of another programming language, nor is it a simplification of anything. It is a
modern scripting language with a wide variety of applications.
JScript .NET is JScript extended with features of class-based languages. All script code in Forsta will however be
wrapped as functions inside a class. This means that you cannot define your own classes in Forsta scripts.
This manual only covers server-side programming, i.e. scripts that are running on the server. It does not consider
client-side scripts (scripts that run on the respondent's browser – typically written in JavaScript), so for example
scripting of HTML elements is outside the scope of this documentation.
Tip:
Copying and Pasting the Script Code from a PDF document
When you copy a script from a PDF document and paste it into the relevant script field in Forsta, the markup is not
kept intact and the script code is pasted as a single line. To prevent this you can either:
• Open the CHM version of this document and copy the scripts from there, or
• Create or open a Wordpad or MS Word file, paste the copied script into the file, and then copy and paste the script
from the Wordpad or MS Word file into Forsta.
-1-
Forsta v2022 Scripting Manual Forsta Confidential
Important!
The eval method will not generate errors if used in Forsta, however it is not supported by Forsta and for
security reasons should not be used in Forsta surveys.
More details on those requirements that are most relevant when working with scripts, follow.
Note: It is not possible to directly access and reference the current function or calling function in fast mode.
-2-
Forsta Confidential Forsta v2022 Scripting Manual
A script node is wrapped inside a class, so when you refer to the sort function you must use the keyword this to
refer to the current instance.
array.sort ({this.sortFunction})
-3-
Forsta v2022 Scripting Manual Forsta Confidential
2.1. Conditions
In conditions you place a logical expression that is evaluated to true or false. If it is true the questions in the THEN-
branch will be presented to the respondent. If it is false, the interview skips the THEN-branch. If the condition has an
ELSE-branch the questions in the ELSE branch will be presented if the condition is false, otherwise they will be
skipped.
To screen respondents that answer "Below 18", insert a condition after the single question with the following syntax:A
f('age') == '1'
(The word "age" here is the question ID of the age question.) Building the conditional expression can be done by
using the condition builder:
-4-
Forsta Confidential Forsta v2022 Scripting Manual
Status is set to "screened" in the properties of the stop node. The interview will end there for all respondents
answering "Below 18", but will continue for all the other respondents.
• Masks based on sets of codes, which are used in "code masks" of single, multi, ranking, open text list,
numerical list, grid, 3D grid questions and loops and "scale masks" of grids.
• "Column masks", which are used in 3D grids to filter the columns and are based on true/false expressions, just
like conditions.
-5-
Forsta v2022 Scripting Manual Forsta Confidential
Scale masks are used to filter scale lists of grid questions. Use the scale mask field in the properties of a grid question
to enter a JScript .NET expression that evaluates to a set of codes. The scale list will be filtered based on this set of
codes.
The list is used in two questions: First you have a multi question q2 which asks what cars you have tested, and then a
3D grid question g5 with a single question q3 which asks what car you did like most of the ones you tested, and a grid
question q4 which asks you to rate the driving experience of the car.
Now, in the 3D grid question g5 you want just the cars answered in q2 to show. This can be achieved with a code
mask with the following code:
f("q2")
that will return a set with the codes of the answers to q2. The answer list of the 3D grid g5 will be filtered so that only
the answers with these codes will be displayed.
When the question q3 is displayed to the respondent, it will only show the cars answered in q2.
-6-
Forsta Confidential Forsta v2022 Scripting Manual
-7-
Forsta v2022 Scripting Manual Forsta Confidential
-8-
Forsta Confidential Forsta v2022 Scripting Manual
There are several functions available to set the text of error messages:
ClearErrorMessage()
takes away the error message at the top of the page (will remove
the default error message).
SetErrorMessage(LangID, message)
defines the text of the error message at the top of the page (will
replace the default error message).
AppendErrorMessage(LangID, message)
adds text to the current page's error message.
ClearQuestionErrorMessage()
takes away the error message for the current question (will
remove the default question error message).
SetQuestionErrorMessage(LangID, message)
defines the text of the error message for the current question.
AppendQuestionErrorMessage(LangID,
message) adds message to the current question's error message.
-9-
Forsta v2022 Scripting Manual Forsta Confidential
For LangID, insert a code to specify which language the error message is for. For example, the code
LangIDs.en
instructs the interview engine to use this error message when the language is English. These language codes, known
as combidents, are listed in Appendix C.
Password Check
Let us say you need to password-protect an open survey. Then you can start the survey with a question asking for a
password that will be the same for all respondents. This can be set up as an open text question with the "Password"
property, so that *s are displayed instead of the text the respondent writes.
To check that the password is correct, you can insert code similar to that shown below in the validation code field of
the open question (in this example the question ID is password):
if(f("password") != "secret")
{ RaiseError(); SetErrorMessage(LangIDs.en,"Incorrect password. Please
enter the correct password to participate in the survey."); }
- 10 -
Forsta Confidential Forsta v2022 Scripting Manual
Note: Dynamic Questions only functions within page objects, and the trigger question(s) and the question(s)
to be triggered, must be on the same page in the survey.
The following questionnaire logic can be used within pages and will update based on the triggers:
Note: The Dynamic Questions functionality is not supported in the CAPI/Kiosk console. Dynamic Questions is
supported in IE8+ (Windows), Firefox 10+ Google Chrome 26+ and Safari 5.1+ (Mac only). The functionality is
only available in surveys using Survey Layouts.
Unlike Advanced WI features, Dynamic Questions have no automatic alternative way of presenting the page if
Dynamic Questions is not supported. A function DynamicQuestionsEnabled (see DynamicQuestionsEnabled
on page 80 for more information) is provided to either screen or provide an alternative routing to respondents
whose browser does not support Dynamic Questions.
- 11 -
Forsta v2022 Scripting Manual Forsta Confidential
If for example you want a rating question to be followed by an open text question if a negative response has been
given, you can use the Dynamic Questions functionality to have that appear on the same page when the negative
response is given.
If you place a single question q9 asking people to respond on a 5-point scale, and you have an open text question
q10 that should be displayed when q9 is answered with “1” or “2”, you can use a question mask as shown below on
the open text question:
f("q9")=="1" || f("q9")=="2"
If you want these questions to appear on the same page, you can place them inside a “Page” object as shown below:
If you set “q9” as a trigger for q10, then q10 will be displayed automatically when a response is given on q9.
The DynamicQuestionsEnabled() function in the condition is used to ensure the page is only displayed to respondents
who are answering in a browser that supports the functionality.
- 12 -
Forsta Confidential Forsta v2022 Scripting Manual
Refer to the separate Survey Designer user guide for further information on the Syntax Highlighter and code
completion functionality.
2. Type more characters to reduce the number of items in the list and jump directly to a member in the list. Use
the arrow buttons to move up and down in the list.
3. Press Enter to select an item.
On functions and methods, a parameters list will automatically pop up to give you information about the number,
names and types of parameters required by a function, template, or attribute. The parameter in bold indicates the next
parameter that is required as you type the function. Where there are different versions of the function with different
parameter lists, you can select which parameter list you wish to view.
- 13 -
Forsta v2022 Scripting Manual Forsta Confidential
1. After the name of a function or method, type an open parenthesis (as you normally would) to open the
Parameters list.
The declaration for the function will pop up under the insertion point. The first parameter in the list appears in
bold. To switch among functions, use the UP or DOWN arrow keys. As you type the function parameters, the
bold changes to reflect the next parameter that you need to enter.
- 14 -
Forsta Confidential Forsta v2022 Scripting Manual
3. Comments
Comments are text added in your scripts that are ignored when the script is run, but may be used to explain aspects
of the code. In JScript .NET you can add comments in two ways:
• /* are placed in front and */ after a comment that runs over several lines.
/* This is a comment on
two lines */
Multi-line comments cannot be nested, because everything after /* will be interpreted as comments, and when the
first */ appears, it will be interpreted as the end of the comment. So any text following the first */ will be treated as
JScript code:
/* This is an example of a
nested comment.
/* Here is the second comment, inside the first.
Both of these comments will terminate here ->*/
This line will be treated as JScript code and result in errors. */
It is recommended that you add a lot of comments in your scripts, to explain to yourself and to others what your script
is supposed to do and what it can be used for. However, as you may later want to comment out large parts of your
scripts, including comments, and it is not possible to nest comments, it is recommended that you always use the
single line comments, as shown below:
// This is a comment on
// two lines
This will make it easy to use /* and */ to comment out large sections of the script later without the nesting problems.
- 15 -
Forsta v2022 Scripting Manual Forsta Confidential
4.1. Naming
Variable and constant names in JScript .NET and question IDs in Forsta begin with an upper- or lowercase letter
(a-z, A-Z) or an underscore (_) and continue with letters (a-z, A-Z), digits (0-9) or underscore (_).
Examples of variable names:
countermakeMoreMoneycar123_tempiThinkThisIsReallyBoring
Note: Variable names are case sensitive, so makeMoreMoney and MakeMoreMoney are not the same variable.
This is a very common mistake.
Even though variable and constant names can start with uppercase letters, it is recommended to follow the convention
of always starting variable and constant names with a lowercase letter. This to easily distinguish it from for
example functions, where the convention is to start with an uppercase letter. Variable and constant names should be
made as descriptive as possible. For example instead of using names like x and y, you should try to describe what
they refer to, e.g. sumOfAllElements or code. When a variable or constant name consists of several words, each
new word is usually started with an uppercase letter.
There are some reserved words that cannot be used as question IDs in Forsta, and some that cannot be used as
variable or constant names in JScript .NET. See the Authoring or Survey Designer User Guide and a JScript .NET
reference manual. In addition, you cannot use names of functions (either the Forsta-provided functions described in
this manual, or functions you define yourself in script nodes (see Functions on page 72 for more information).
- 16 -
Forsta Confidential Forsta v2022 Scripting Manual
var x, y : int;
You do not need to use typed variables, but scripts that use untyped variables are slower and more prone to errors.
var counter;
Without a specified data type, the default type for a variable or constant is Object. Without an assigned value, the
default value of the variable is undefined.
You can give a variable an initial value without declaring its type:
var counter = 0;
Untyped constants are defined in the same way:
const maxSelected = 100;
4.4. Null
null is used as "no value" or "no object". In other words, it holds no valid number, string, Boolean, array, or object
(array and objects are complex data types we will get back to later). You can erase the contents of a variable (without
deleting the variable) by assigning it the null value. Note that the value undefined and null compare as equal
using the equality (==) operator.
In JScript, null does not compare as equal to 0 using the equality operator. This behavior is different from other
languages, such as C and C++.
- 17 -
Forsta v2022 Scripting Manual Forsta Confidential
You must set the "Not required" property on both questions. It is quite easy to write validation code to give an error
message when both questions are answered (as in the figure above), but the respondent cannot de-select the
answers since this is not possible with radio-buttons. Then you must remove the answers to the questions in the
validation code, i.e. setting them to the null value:
if(f("present1").toBoolean() && f("present2").toBoolean()) //both
questions answered
{
//Remove answers on both questions:
f("present1").set(null);
f("present2").set(null);
//Provide error message
RaiseError();
SetErrorMessage(LangIDs.en,"Please select either a bottle of wine or a
CD.");
}
toBoolean is used to check if there is an answer on a question (see toBoolean on page 25 for more information).
set is used to set the value of a question (see get and set on page 42 for more information).
This validation code will give this result when trying to move to the next page after selecting an answer on both
questions:
- 18 -
Forsta Confidential Forsta v2022 Scripting Manual
4.5. Types
A data type specifies the type of value that a variable, constant, or function can accept. Type annotation of variables,
constants, and functions helps reduce programming errors by making sure data that is assigned has the right types.
Furthermore, type annotation also produces faster, more efficient code.
There are several primitive types of values in JScript .NET. In the following chapters we will present these types. We
have grouped them as numeric, Boolean and string values.
Primitive types are types that can be assigned a single literal value. We will be looking at more complex types later.
4.5.1. Numeric
There are two main types of numeric data in JScript:
• Integers.
• Floating-point data.
4.5.1.1. Integers
Positive whole numbers, negative whole numbers, and the number zero are integers. They can be represented in
base 10 (decimal), base 8 (octal), and base 16 (hexadecimal). Most numbers in JScript are written in decimal. Octal
and hexadecimal rarely have any practical purpose in scripting; however, you should be aware of their denotation –
particularly for octals, since it may cause unexpected results when a number is interpreted as an octal when it was
supposed to be decimal.
You denote octal integers by prefixing them with a leading 0 (zero). They can only contain digits 0 through 7. Any
number with a leading 0 will be interpreted as an octal, as long as it is not containing the digits 8 and/or 9, in which
case it is interpreted as a decimal number.
- 19 -
Forsta v2022 Scripting Manual Forsta Confidential
You denote hexadecimal (hex) integers by prefixing them with a leading "0x" (zero and x or X). They can contain digits
0 through 9, and letters A through F (either uppercase or lowercase) only.
Both octal and hexadecimal numbers can be negative, but they cannot have a decimal portion and cannot be written
in scientific (exponential) notation.
JScript .NET supports the following integral data types: byte, ushort, uint, ulong, sbyte, short, int,
long. Variables of any integral data type can represent only a finite range of numbers. If you attempt to assign a
numeric literal that is too large or too small to an integral data type, a type-mismatch error will be generated at compile
time.
• NaN(not a number). This is used when a mathematical operation is performed on inappropriate data, such as
strings or the undefined value.
• Infinity. This is used when a positive number is too large to represent in JScript.
• -Infinity (negative Infinity). This is used when the magnitude of a negative number is too large to
represent in JScript.
• Positive and Negative 0. JScript differentiates between positive and negative zero.
JScript supports the following floating-point data types:
- 20 -
Forsta Confidential Forsta v2022 Scripting Manual
float(single-precision floating- The float type can represent numbers as large as 1038 (positive
point) or negative) with an accuracy of about seven digits, and as small as
10-44. The float type can also represent NaN (Not a Number),
positive and negative infinity, and positive and negative zero.
This type is useful for large numbers where you do not need
precise accuracy. If you require very accurate numbers, consider
using the Decimal data type.
Number, double (double- The Number or double type can represent numbers as large as
precision floating-point) 10308 (positive or negative) with an accuracy of about 15 digits, and
as small as 10-323. The Number type can also represent NaN (Not a
Number), positive and negative infinity, and positive and negative
zero.
This type is useful when you need large numbers but do not need
precise accuracy. If you require very accurate numbers, consider
using the Decimal data type.
decimal The decimal type can accurately represent very large or very
precise decimal numbers. Numbers as large as 1028 (positive or
negative) and with as many as 28 significant digits can be stored as
a decimal type without loss of precision. This type is useful when
rounding errors must be avoided.
The decimal data type cannot represent NaN, positive Infinity, or
negative Infinity.
4.5.2. Boolean
The Boolean data type can only have two values. They are the literals
true
and
false
representing logical values. They are used in conditions. The THEN branch is executed when the expression
evaluates to the Boolean value true, the ELSE branch when the expression evaluates to the Boolean value false.
JScript .NET automatically converts true and false into 1 and 0 when they are used in numerical expressions. When
numbers are used in Boolean expressions, 0 is interpreted as false and any other number as true.
Note: When you write JScript .NET code, you can have as many line breaks and blanks as you like in your
code, but never have a line break inside a string. If you have a line break inside a string, you will get an error
message.
However, there are codes you can insert for special formatting characters. E.g. for a line break use \n:
- 21 -
Forsta v2022 Scripting Manual Forsta Confidential
"I need a line break here\n and want to continue on the next line"
For apostrophe, use \':
'I can\'t stand this anymore'
Below is a table describing the special formatting characters:
Character Meaning
\\ Backslash
\n New line
\r Carriage return
\t Horizontal tab
\b Backspace
4.5.3.1. Unicode
Jscript.NET supports Unicode characters in strings. They can be used like any other characters, but note that the
encoding of the survey pages will be set according to the settings for the active language, so that for example for
English, which by default will be set to have encoding “Western European (ISO)”, Unicode characters will not be
displayed correctly on the survey page. Only Unicode languages will display Unicode characters correctly. You should
also ensure you set the right codepage (Unicode - 65001) if using Unicode characters in SendMail and
SendMailMultiPart scripts.
- 22 -
Forsta Confidential Forsta v2022 Scripting Manual
Here is a small example showing first how the number 1234 (integer) can be converted to the string “1234” and then
to a double.
var i : int = 1234; var d : double;
var s : String; s = String(i);
Now the variable s holds the string “1234”. This type of conversion is called widening, since all possible integer
values can be converted to string and string can also hold other values. Let us continue the example:
d = double(s);
Now the variable d holds the double 1234. This type of conversion is called narrowing since there are a lot of possible
string values that cannot be converted to double (for example the string “Forsta”). Explicit narrowing conversions will
usually work, but with loss of information. The string “Forsta” converted to a double will give NaN (not a number). But
some types are incompatible and will throw an error, and for some values there is not sensible value to convert to.
Implicit conversion occurs automatically when values are assigned to variable of a certain type. The data type of the
variable determines the target data type of the expression conversion.
Here is a similar example to the one above showing first how the number 1234 (integer) can be converted to the string
“1234” and then to a double.
var i : int = 1234;
var d : double;
var s : String;s = i;
Now the variable s holds the string “1234”. It was converted to string since the receiving variable where of type string.
This is an example of widening implicit conversion. Let us continue the example:
d = s;
Now the variable d holds the double 1234. This is an example of a narrowing conversion.
When this code is compiled, compile-time warnings may state that the narrowing conversions may fail or are slow.
Implicit narrowing conversions may not work if the conversion requires a loss of information.
4.6.1.2. parseFloat
parseFloat returns a floating-point number converted from a string. It is a method of the Global Object. The Global
Object has no syntax, so its methods can be called directly:
parseFloat(numString)
- 23 -
Forsta v2022 Scripting Manual Forsta Confidential
The required numString argument is a string that contains a floating-point number. The function will read numbers
from the beginning of the string and will stop at the first character that cannot be interpreted as part of a floating-point
number. If the string does not begin with a floating-point number, NaN will be returned.
parseFloat("2.1e4xyz")
returns 21000 (2.1 * 104).
4.6.1.3. isNaN
The isNaN method returns true if the value is NaN, and false otherwise. It is a method of the Global Object. The
Global Object has no syntax, so its methods can be called directly: You typically use this function to test return values
from the parseInt and parseFloat methods.
isNaN(num)
num is a numeric value to test.
4.6.1.4. isFinite
The isFinite method returns true if the value is any other value than NaN, negative infinity or positive infinity. If it
is any of those three, it returns false. It is a method of the Global Object. The Global Object has no syntax, so its
methods can be called directly:
isFinite(num)
num is a numeric value to test.
4.6.1.5. toString
toString is a method of the Object object, which means it is available in any other JScript .NET object. It is used to
convert a variable into a string. Sometimes this must be done to a variable before inserting it in a question with the
set method (see get and set on page 42 for more information).
4.6.1.6. valueOf
valueOf is a method of the Object object, which means it is available in any other JScript .NET object. It returns the
primitive value of the specified object, i.e. the numeric value of a number, the string value of a string etc.
4.6.2.1. toNumber
toNumber is a method you can use to convert the value of a question from a string into a Number (double) (see
Floating-point Data on page 20 for more information):
f(qID).toNumber()
qID is the question ID.
Note: The toNumber method requires that the question is answered, and that the value stored for the
question can be converted to a number. If not, it will return NaN (not a number).
4.6.2.2. toInt
toInt is a method you can use to convert the value of a question from a string into an integer (see Integers on page
19 for more information):
f(qID).toInt()
qID is the question ID.
- 24 -
Forsta Confidential Forsta v2022 Scripting Manual
Note: The toInt method requires that the question is answered, and that the value stored for the question can
be converted to an integer. If not, it will fail, terminate the interview with an “Internal server error” and send
an error report to the “Email address to receive emails triggered by scripting errors in interview”. The method
should either only be used when you know that there will always be a valid response to the question, or you
should check that the response is numeric before using toInt (for example using IsInteger).
4.6.2.3. toDecimal
toDecimal is a method you can use to convert the value of a question from a string into a decimal (see Floating-
point Data on page 20 for more information):
f(qID).toDecimal()
qID is the question ID.
Note: The toDecimal method requires that the question is answered, and that the value stored for the
question can be converted to a Decimal. If not, it will fail, terminate the interview with an “Internal server
error” and send an error report to the “Email address to receive emails triggered by scripting errors in
interview”. The method should either only be used when you know that there will always be a valid response
to the question, or you should check that the response is numeric before using toDecimal (for example using
IsNumeric).
Note: Always use toNumber, toInt or toDecimal when you use expressions involving the operators <, <=,
>= or >, or when doing arithmetic operations on the answers.
4.6.2.4. toBoolean
toBoolean is a method that converts the variable into a Boolean (true/false). It can be used to check if a question
has been answered, or for a single question with the Boolean property, if it has been answered with the true or false
answer alternative.
Note: The Boolean question property mentioned in the last sentence above is only available in surveys using
the Optimized Database format.
f(qID).toBoolean()
If the respondent has answered the question with question ID qID, the expression will yield true, if not, false. Or, if
qID is a Boolean question, the expression will yield true if the respondent has chosen the answer corresponding to
true (1), and false if the respondent has chosen the answer corresponding to false (0)
You have already seen toBoolean used in the Removing an Answer in a Single or Grid Question example.
- 25 -
Forsta v2022 Scripting Manual Forsta Confidential
4.6.2.5. toDate
toDate can be used on date questions to return a .NET structure representing the selected date value. Note that this is
not the same as a JScript Date object. JScript supports the use of .NET structures, but not the declaration of new
ones, so sometimes it may be easier to create a JScript Date object instead for scripting purposes. See The Date
Object (chapter 14.1).
f(qID).toDate()
returns a strongly-typed Nullable DateTime object representing the date answered.
4.6.2.6. day
day can be used on date questions to get the day part of the specified date.
f(qID).day()
returns the integer value (1 - 31) representing the "day" part of the specified date. 0 is returned if no date is specified.
4.6.2.7. month
month can be used on date questions to get the month part of the specified date.
f(qID).month()
returns the integer value representing month part of the date specified, 0 if no date is specified. Conventional
numbering of months is used (1 = January, 2 = February etc.).
4.6.2.8. year
year can be used on date questions to get the year part of the specified date.
f(qID).year()
returns the integer value representing year part of the date specified, 0 if no date is specified.
4.6.2.9. datestring
datestring can be used on date questions to get a textual representation of the specified date.
f(qID).datestring()
returns the textual representation of the chosen date in accordance to the current language setting (for example,
English gives "Friday, April 25, 2010"). The same result will be achieved (a textual representation of the date in
accordance with the current language setting) when performing response piping on a date question.
Note: The date question type is only available in surveys using the "Optimized database format".
- 26 -
Forsta Confidential Forsta v2022 Scripting Manual
Operator Description
+ Addition
* Multiplication
/ Division
++ Increment and then return value (or return value and then increment)
- 27 -
Forsta v2022 Scripting Manual Forsta Confidential
-- Decrement and then return value (or return value and then decrement)
x = 3 x = 3
y = ++x y = x++
Result: x = 4 and y = 4 Result: x = 4 and y = 3
In the first example, x is increased by 1 before the value is returned and stored in y. In the second the value of x is
returned and stored in y first, and then x is increased by 1. We recommend that you be very careful when using these
operators.
Operator Description
|| logical or
! logical not
Operator Description
== Equal
!= Not equal
- 28 -
Forsta Confidential Forsta v2022 Scripting Manual
Operator Description
+ String concatenation
Operator Description
Sets the variable on the left of the = operator to the value of the expression on its
=
right.
Increments the variable on the left of the += operator by the value of the expression
+= on its right. When used with strings, the value to the right of the += operator is
appended to the value of the variable on the left of the += operator.
Decrements the variable on the left of the -= operator by the value of the expression
-=
on its right.
- 29 -
Forsta v2022 Scripting Manual Forsta Confidential
Multiplies the variable on the left of the *= operator by the value of the expression on
*=
its right.
Divides the variable on the left of the /= operator by the value of the expression on its
/=
right.
Takes the modulus of the variable on the left of the %= operator using the value of the
%=
expression on its right.
The following table explains the operators +=, -=, *=, /= and %=.
Operator Equivalent to
x += y x = x+y
x -= y x = x-y
x *= y x = x*y
x /= y x = x/y
x %= y x = x%y
5.7. new
new is used to create new objects. Its use is described in Arrays, Objects, Working with Sets and Predefined JScript
.NET Objects.
- 30 -
Forsta Confidential Forsta v2022 Scripting Manual
In the text field of the question or info where you want to pipe in the response to the musical question, you can use
this code:
^f("musical").get() == "98" ? f("musical_98_other") : f("musical")^
f("musical").get() will return the code of the answer to musical (see get and set on page 42 for more
information). If this is equal to 98, the answer from the "Other" text box should be piped in
(f("musical_98_other")). If not, use normal text substitution with f("musical") so that the answer text will be
piped in.
If you instead want an empty string (i.e. no text at all) to appear when the question is not answered, use this
expression in the question where you want to pipe in the answer:
- 31 -
Forsta v2022 Scripting Manual Forsta Confidential
Note: Expressions inside ^ (carets) in question text fields, title fields and answer/scale lists in Forsta must
always return strings. You cannot run JScript .NET statements inside ^'s, however you can call a function
that returns a string.
5.9. Coercion
You can set up JScript expressions that involve values of different types without the compiler raising an exception.
Instead, one of the types will automatically be changed (coerced) to that of the other before performing the operation.
The compiler will allow all coercions unless it can prove that the coercion will always fail. Any coercion that may fail
generates a warning at compile time, and many produce a runtime error if the coercion fails.
For example, if you add a string “Forsta“ and the number 8.5, the number will be converted to a string so that the
expression
"Forsta"+8.5
will give the string "Confirmit8.5", the concatenation of the strings "Forsta" and "8.5".
In JScript :NET you can also force what type a value should be coerced to by using the target type name (see Types
on page 19 for more information).
The table below shows what the result will be when using the operator + between values of different types. It
illustrates what the order of precedence within the types. If a string is involved, the other types are converted to string.
For numbers it will give the number as a string, the Boolean value false will give the string "false" and true the
string "true". null will be converted to the string "null". An int is converted to a float in an expression with a float
value. Boolean true will be converted 1 and false to 0 when used in an expression with a numeric value. null will
be converted to 0 when used in an expression with a numeric value.
- 32 -
Forsta Confidential Forsta v2022 Scripting Manual
As all values returned from questions in Forsta are strings, and strings have precedence over all other types, you may
have to use some sort of conversion function to change the type before using the value from a question in your
scripts.
Exercise 1:
Find the result of this expression.
(As will be shown in the next chapter, expressions within brackets will be calculated separately before the resultant
value is concatenated with the other strings, so e.g. 192+15=207 is the resultant value from the first part that is
brought into the string.)
(192+15)+" is not the same as "+(true+206)+", but this isn't really
"+true
See the answer in APPENDIX A Answers to Exercises.
Operator
1 ()
2 !, -- , ++, -, new
3 *, /, %
4 +, -
- 33 -
Forsta v2022 Scripting Manual Forsta Confidential
7 &&
8 ||
9 ?:
- 34 -
Forsta Confidential Forsta v2022 Scripting Manual
6. Simple Statements
A statement is an instruction that makes a program perform some action.
Statements are separated either with a line break or a semicolon (;)
More than one statement may occur on a single line of text, provided that they are separated by semicolons.
A semicolon is not needed between statements that occur on separate lines, however it is recommended to use it
anyway in case the line breaks are removed later.
A statement may be written over multiple lines of text. However, do not use line break inside string constants as this
will give a script error. If you need a line break inside a string, you must use \n (see Characters and Strings on page
21 for more information). Also, postfix increment and decrement operators must appear on the same line as their
argument (e.g. i++ and i--, (see Arithmetic Operators on page 27 for more information), continue and break
keywords must appear on the same line as their label (see The break Statement on page 67 for more information),
and return must appear on the same line as its expression (see The return Statement on page 163 for more
information).
A group of JScript statements surrounded by curly brackets ({}) is called a block. Statements within a block can
generally be treated as a single statement. They are used to group a set of statements inside branches of a condition,
or inside loops and functions.
6.1. Declarations
We have used this to declare JScript .NET variables and constants.
var variableName {: type} {= expression};
or
const constantName {: type} = expression;
as for example in
var x : int = 12;
which both identifies the variable x and causes it to be implicitly declared as a variable of type int and initialized to the
value 12.
Variables and constants may or may not be bound to a specific data type.
var x = 12;
Variables may not be initialized to any value. Constants have to be initialized.
var x;
- 35 -
Forsta v2022 Scripting Manual Forsta Confidential
6.3.1. if
if( condition )
{
statements }
If the expression inside the parenthesis is true, the statements inside the curly brackets, { and }, are executed. If the
condition is false, then the statements are skipped and execution continues on the next program line.
Note that the parentheses around the condition are required.
If-then conditions are often used when creating scripts in Forsta, especially for validation code.
We have used if conditions several times already. See the examples in Validation Code, Null and toBoolean for more
information.
6.3.2. if-else
if( condition )
{
statements }
else
{
statements }
If the condition inside the parenthesis is true, then the first set of statements is executed. If the condition is false,
then the second set of statements is executed.
Exercise 3:
What values will x and y have after running these two code samples (separately):
//Code sample 1
if(x<y)
{
x++;
}
else
{
y++;
}
//Code sample 2
if(x<y)
{
x++;
}
y++;
- 36 -
Forsta Confidential Forsta v2022 Scripting Manual
if(x<y)
x++;
else
y++;
However, it is easy to make mistakes when you do not use the brackets.
if(x<y)
x++;
y++;
is equivalent to sample 2 in the previous exercise, but that might be hard to spot. So it is recommended to always use
the curly brackets, both for clarity and also to simplify later modifications such as adding another statement within a
branch in the if statement.
Using switch to set Values for each of the Answer Alternatives on a Single
- 37 -
Forsta v2022 Scripting Manual Forsta Confidential
Let us say we have a single question where the respondent picks from a list of different concepts. Each of these has a
price, and we want to set the price in a hidden numeric question based on which of the concepts the respondent has
picked. The value in the hidden numeric question may e.g. be used in calculations later in the questionnaire. The
single question has question ID "concept" and the numeric question has question ID "price".
Here are two different ways of scripting this; the first using if and the second using switch. As you see, switch gives
more compact code that is easier to read:
//using if:
if(f("concept")=="1")
{
f("price").set(234);
}
else if(f("concept") == "2")
{
f("price").set(249);
}
else if(f("concept") == "3")
{
f("price").set(244);
}
else if(f("concept") == "4")
{
f("price").set(229);
}else
{
f("price").set(271);
}
//using switch:
switch(f("concept").get())
{
case "1":
f("price").set(234);
break
case "2":
f("price").set(249);
break
case "3":
f("price").set(244);
break
case "4":
f("price").set(229);
break
default:
f("price").set(271);
}
- 38 -
Forsta Confidential Forsta v2022 Scripting Manual
7. Arrays
Arrays are a special type of JavaScript object. An object is referred to as a complex data type because it is built from
primitive types (see The Array Object on page 215 for more information).
Arrays are objects that are capable of storing a sequence of values in one variable. A single index number (for a one-
dimensional array) or several index numbers (for an array of arrays, or a multidimensional array) references the data
in the array. You can refer to an individual element of an array with the array identifier followed with the array index in
square brackets ([]). The indexes are numbered from 0 to 1 less than the number of elements in the array. To refer to
the array as a whole, use the array identifier.
There are two types of arrays in JScript, JScript arrays (the Array object), and typed arrays. While the two types of
arrays are similar, there are a few differences. JScript arrays and typed arrays can interoperate with each other.
Consequently, a JScript Array object can call the methods and properties of any typed array, and typed arrays can call
many of the methods and properties of the Array object. Furthermore, functions that accept typed arrays accept Array
objects, and vice-versa.
- 39 -
Forsta v2022 Scripting Manual Forsta Confidential
Array("Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sund
ay");
You can also define an empty array:
var weekday = new Array();
or an array with size 7:
var weekday = new Array(7);
and then assign values to the elements:
weekday[0] = "Monday";
weekday[1] = "Tuesday";
weekday[2] = "Wednesday";
weekday[3] = "Thursday";
weekday[4] = "Friday";
weekday[5] = "Saturday";
weekday[6] = "Sunday";
The difference between declaring the array as a JScript array instead of as a typed array (see Declaring Typed Arrays
on page 39 for more information) is that when it is defined as a typed array, all elements in the array must be of that
type.
Also, in a JScript array you can insert elements of any type, including complex types such as other arrays or objects.
Another difference is that in a JScript array you can at any time add new elements, for example another weekday.
This can be done no matter how the JScript array is defined, even when defined with the length specified, as in the
example with new Array(7).
weekday[7] = "Lastday";
(this would be a good idea to be able to at least occasionally finish projects before deadlines). The array has now 8
elements (0-7). In typed arrays, you cannot add new elements to the array, just modify existing elements.
And finally, in a JScript array you can have "holes". You can for example add a 50th element (with index 49):
weekday[49] = "Extremelyoverdueday";
without defining all the elements in between. The size of the array will be 50, even though elements with index 8,…,48
have not been defined.
- 40 -
Forsta Confidential Forsta v2022 Scripting Manual
7.3. length
The length of an array is its size, i.e. the number of elements in it. length is the index of the last element+1.
When we declared the weekday array previously, we declared an array of length 7:
var weekday = new Array(7);
The array could have been declared without specifying length:
var weekday = new Array();
Initially, the length would then have been 0, but the length would increase as elements were added. And as explained
in the previous chapter, the length will always be 1 more than the last index of the array, as the indexes start with 0.
This is true even if there are empty elements in it.
It is also possible to declare multidimensional JScript arrays and arrays of JScript arrays. Refer to a JScript .NET
reference for more information.
- 41 -
Forsta v2022 Scripting Manual Forsta Confidential
Note: The Date question type is only available when using the Optimized Database format.
8.2. label
f(qID).label()
This method is used to access the question title of a question. This method is available on open text, single, multi,
numeric, date, ranking, open text list, numeric listand grid questions.
f("q1").label()
will return the title of the question q1.
8.3. text
f(qID).text()
This method is used to access the question text of a question. This method is available on open text, single, multi,
numeric, date, ranking, open text list, numeric list and grid questions.
- 42 -
Forsta Confidential Forsta v2022 Scripting Manual
f("q1").text()
will return the question text of the question q1.
8.4. instruction
f(qID).instruction()
This method is used to access the question instruction of a question. This method is available on open text, single,
multi, numeric, date, ranking, open text list, numeric listand grid questions.
f("q1").instruction()
will return the question instruction of the question q1.
8.5. value
f(qID).value()
value can be used on single questions to access the code of the answer to the single question (similar to get on a
single question).
8.6. valueLabel
f(qID).valueLabel()
Use this method on a single question to access the label of the answer to the single question in the current language.
8.7. domainValues
f(qID).domainValues()
This will return an array with all codes from the answer list of a single, multi, ranking, open text list, numeric list or
grid question, headers excluded.
This method is subject to masking, so if a code mask is used to filter the answer list then this will only return the codes
of the answers that are displayed to the respondent.
The method is also subject to randomization. That is, if the answer list is randomized, then the array will be returned
randomized.
8.8. domainLabels
f(qID).domainLabels()
This method will give an array with all the labels (answer texts) on the question, headers excluded. This is the
corresponding answer texts to the codes returned with domainValues. They will be in the current language. The
method will give all possible answer texts from the answer list of a single, multi, ranking, open text list, numeric
list or grid question. This is also subject to masking.
The method is also subject to randomization. That is, if the answer list is randomized, then the array will be returned
randomized.
8.9. categories
f(qID).categories()
categories will return an array with the codes of the items that have been answered on a multi, ranking, open
text list, numeric list or grid question. For a multi question, this will be the codes of the answers that have been
selected, for a grid this will be the codes of the answers that have an answer. Usually a grid is required, so categories
will be equal to domainValues for a grid. But if the grid is not required, they may differ.
Note: If a code mask is used to filter the answer list, then this will only return the codes of those answers that
are displayed to the respondent. The f() will not return the results of a combination of answers selected by the
respondent and answers added by script.
- 43 -
Forsta v2022 Scripting Manual Forsta Confidential
Then you need a script node to copy the response from musicals into musicals_hidden. Copying answers from one
question to another hidden question can also be something you need to do for example to have different, shorter
answer texts in response piping in a later question, or to have different texts for reporting.
f("musicals_hidden").set(f("musicals").categories());
For this script to work, musicals and musicals_hidden need to be of the same question type and have exactly the
same answer lists (same number of items and same codes).
The script is to be placed after the musicals question:
In the info node you may now refer to the musicals_hidden question in your response piping:
You have seen these musicals: ^f("musicals_hidden")^
If the respondent for example answers like this:
- 44 -
Forsta Confidential Forsta v2022 Scripting Manual
8.10. categoryLabels
f(qID).categoryLabels()
This method will return an array with the labels of the items that have been answered on a multi, ranking, open text
list, numeric listor grid question in the current language, i.e. the texts from the answer list corresponding to the
codes returned from categories.
8.11. values
f(qID).values()
values will return an array with the answers stored in the database for a grid, multi, ranking, open text list or
numeric list question.
• For a grid question this will be the codes of the answers to the questions (from the scale).
• For ranking, open text list or numeric list questions it will be the numbers or texts answered for each item in
the answer list.
- 45 -
Forsta v2022 Scripting Manual Forsta Confidential
Note: If the multi question is hidden, then the return will be 1 (selected) and null/blank (not selected).
8.12. getType
f(qID).getType()
getType will return the type of the question. The result returned for the various question types are:
Note: You cannot set the value for an Image Upload, Audio or Video Capture question.
8.13. GetAdditionalColumnValue
This is a survey engine scripting method used to retrieve data from an additional column or columns associated with a
specific table inside of a table lookup list.
f('qid').GetAdditionalColumnValue(code, additionalColumnName)
where:
code is the id to query from the lookup table.
additionalColumnName is the name of the additional column from which data is returned.
This will return the data in the specified additional column name in the table lookup for the question “qid” for the code
supplied, in the same language the interview is being completed in.
In this example where there is a single question “sales_rep” based on a database lookup “car_rep”:
- 46 -
Forsta Confidential Forsta v2022 Scripting Manual
The “salesRepDetails” info node contains the following piping of the additional columns “office” and “joined_year”:
Note: In most cases the code value supplied in the method will refer to the f(‘qid’).get() for the question that
the lookup is based on.
You can perform a test to check whether the code exists in the table used as qid’s answerlist. If the code doesn't exist
in the table lookup then the method will return "undefined".
To test if the code exists in the table lookup, and display an error message if not, add the following:
if(f('qid').GetAdditionalColumnValue(code,additionalColumnName)==undefine
d)
{
RaiseError();
SetQuestionErrorMessage(LangIDs.en,”Error – that code doesn’t exist in
the lookup table”);
}
Note: The GetDBColumnValue function is described here (see GetDBColumnValue on page 98 for more
information).
8.14. any
f(qID).any(code1,…,coden)
- 47 -
Forsta v2022 Scripting Manual Forsta Confidential
any will return true if any of the codes listed is answered on a single or multi question, or if any of the items for these
codes have a response on a grid, multi, ranking, open text list or numeric list question, or false if none of these
items has a response. The method is for example useful in conditions.
8.15. all
f(qID).all(code1,…,coden)
all will return true if all of the codes listed is answered on a multi question, or if all of the items for these codes has a
response on a grid, multi, ranking, open text list or numeric list question, or false if none of these items has a
response. The method is for example useful in conditions.
8.16. none
f(qID).none(code1,…,coden)
none will return true if none of the codes listed is answered on a single or multi question, or if none of the items for
these codes has a response on a grid, multi, ranking, open text list or numeric list question, or false if either of
these items has a response. The method is for example useful in conditions.
8.17. between
f(qID).between(from, to)
between will return true if the answer to a numeric question or an item of a numeric list question is between the
from value and the to value, or false if not. This means the value answered is higher than or equal to the from value
and lower than or equal to the to value. The method is for example useful in conditions.
8.18. isNearBy
f(qID).isNearBy(latitude, longitude, distance)
isNearBy can be used on Geolocation questions, and will return true if the position recorded in the question is within a
given distance in meters from the position defined by the latitude and longitude. Latitude, longitude and distance are
all numeric (double).
- 48 -
Forsta Confidential Forsta v2022 Scripting Manual
8.20.2. Date
Question ID: "birthday".
- 49 -
Forsta v2022 Scripting Manual Forsta Confidential
Note: The Date question property is only available when using the Optimized Database format.
- 50 -
Forsta Confidential Forsta v2022 Scripting Manual
- 51 -
Forsta v2022 Scripting Manual Forsta Confidential
Note: The Boolean question property is only available when using the Optimized Database format.
- 52 -
Forsta Confidential Forsta v2022 Scripting Manual
- 53 -
Forsta v2022 Scripting Manual Forsta Confidential
- 54 -
Forsta Confidential Forsta v2022 Scripting Manual
- 55 -
Forsta v2022 Scripting Manual Forsta Confidential
- 56 -
Forsta Confidential Forsta v2022 Scripting Manual
8.20.10. Referencing the Elements of a Multi, Ranking, Open Text List, Numeric
List or Grid
Each item in the answer list of a multi, ranking, open text list, numeric list or grid can be referenced with syntax quite
similar to the syntax for referencing the items in an array. But instead of a numeric index starting at zero, you refer to
the elements of a multi or a grid by using the code of the element. The code is a string. For example
f("q1")["3"]
will be the item with code "3" in the multi or grid q1.
When you use this syntax to access an element of a grid or a multi, you can use the following methods:
• get, set, label and getType for the elements of a multi, ranking, open text list or numeric list question.
label will then give the label of the answer in the current language. getType will return "DICHOTOMY" if it is
a multi, "NUMERIC" if it is a numeric list, and "OPEN" if it is any of the other types.
• get, set, label, value, valueLabel, domainValues, domainLabels for the elements of a grid
question. label will then give the label of the answer (from the answer list) in the current language. value
will return the code of the answer (from the scale) to that element of the grid. valueLabel will return the
corresponding answer text (from the scale) in the current language. domainValues and domainLabels will
respectively return all possible codes from the scale and the corresponding labels (answers) from the scale in
the current language. getType will return "CODED".
Using the same multi and grid from the previous example, the examples below show methods that can be used on the
single elements of a multi or a grid.
- 57 -
Forsta v2022 Scripting Manual Forsta Confidential
8.20.11. Loops
The same methods may be used on a loop node as on a single question. They return the same items as the single,
except for label, which will return the loop's ID (not the loop's title, which is only used in reporting).
- 58 -
Forsta Confidential Forsta v2022 Scripting Manual
Below are the results from the first iteration of the loop:
The first four methods (get, label, value and valueLabel) can only be used inside the loop and will give results
for the current iteration. domainValues and domainLabels can also be used outside of the loop.
8.20.12. 3D Grid
None of the methods apply directly to 3D grids. Instead, refer to the questions contained in the 3D grid by their
question IDs.
An other specify item on a 3D grid can be accessed in a similar way to other specify on other questions:
f("qid_code_other").get()
qid would then be the question id of the 3D grid, and code would be the code of the answer with other specify.
1. "Important"
- 59 -
Forsta v2022 Scripting Manual Forsta Confidential
2. "Design"
Open Date Nume Single Multi Open Nume Ranki Grid Geoloc Element Eleme Loop
text ric Text ric ng ation of multi, nt of
List List open text grid
list,
numeric
list,
ranking
String .get () X X X X X X X X
.set () X X X X X X X X X X X X X
.label () X X X X X X X X X X X X X
.text () X X X X X X X X X X
.instruction X X X X X X X X X
()
.value () X X X X X X
.valueLabel X X X
()
.getType X X X X X X X X X X X X X
Array .domainVal X X X X X X X X
ues ()
.domainLab X X X X X X X X
els ()
.categories X X X X X
()
.categoryLa X X X X X
bels ()
.values () X X X X X
.any() X X X X X X
- 60 -
Forsta Confidential Forsta v2022 Scripting Manual
Boole .all() X X X X X
an .none() X X X X X X
.between() X X1
.isNearBy() X
Doubl .latitude() X
e .longitude() X
- 61 -
Forsta v2022 Scripting Manual Forsta Confidential
9. Loop Statements
Loop statements are used to repeat the execution of a set of statements as long as a particular condition is true.
There are three types of loop statements in JScript .NET: the while statement, the do while statement and the for
statement. The loop statements in JScript .NET are similar to the loop construct in Forsta, but there is a difference: In
a loop in Forsta, a set of questions is repeated for the items in the loop list (subject to masking). In a JScript .NET
loop, a set of statements is repeated until a condition is evaluated to false.
The 3D grid contains 3 numeric list questions: q2 (sleep), q3 (work) and q4 (leisure).
The following code is entered in the validation code field to evaluate the respondent's answers:
- 62 -
Forsta Confidential Forsta v2022 Scripting Manual
f("q2")[code].toNumber()+f("q3")[code].toNumber()+f("q4")[code].toNumber(
);
if(sum != 24)
{
correctSum = false;
}
i++;
}
if(!correctSum)
{
RaiseError();
SetQuestionErrorMessage(LangIDs.en,"Please make sure that the total
number of hours for each day equals 24. Currently the sum for
"+f("q2")[code].label()+" is "+sum+".");
}
Let us see what actually happens here when the question is answered as in the picture above.
The first statement,
var codes = f("q2").domainValues();
declares an array called codes, which contains all the codes from the answer list of q2. (Since q2, q3 and q4 are all
inside the same 3D grid, they share the same answer list, so we could have used any of these questions to populate
the array.) We have used the default codes ("1","2","3","4","5","6","7") in this answer list, so the first statement
declares an array of length 7 where the items have the following values:
codes[0] = "1"
codes[1] = "2"
codes[2] = "3"
codes[3] = "4"
codes[4] = "5"
codes[5] = "6"
codes[6] = "7"
The main advantage with using domainValues here is that we can do any changes we like to this answer list
(including adding/removing items and changing the codes) without having to change the script.
Then in the next statement we declare a new variable i as an integer with the initial value 0 (zero). This will be used
to index the array. After that the Boolean correctSum is declared with the initial value true.
var i : int = 0;
var correctSum : Boolean = true;
So, when we enter the while loop the first time, the condition will evaluate to true because i is 0, which is less than
the length of the array codes (which is 7), and correctSum is true.
while(i<codes.length && correctSum)
With i equal to 0, the first statement
var code = codes[i];
will set code to the first code, "1".
A variable sum is then set in the statement
- 63 -
Forsta v2022 Scripting Manual Forsta Confidential
f("q2")[code].toNumber()+f("q3")[code].toNumber()+f("q4")[code].toNumber(
);
to 7+8+9, which is 24. (This is the numbers entered for Monday in the 3D grid, see screenshot above.)
The condition in the following if statement will evaluate to false, so the statement inside the curly brackets will not
be executed. Consequently, correctSum will remain true:
if(sum != 24)
{
correctSum = false;
}
At the end of the loop i is increased by 1:
i++;
That completes the first iteration of the while statement. The next time the condition in the while statement is
evaluated, i is 1. 1 is less than 7, and correctSum is still true, so the condition still evaluates to true, and the
statements are to be run a second time.
while(i<codes.length && correctSum)
With i equal to 1, the first statement
var code = codes[i];
will set code to the second code, "2".
The sum will now be 7+11+6 (Tuesday), which is 24.
var sum : int =
f("q2")[code].toNumber()+f("q3")[code].toNumber()+f("q4")[code].toNumber(
);
The condition in the if statement will again evaluate to false (so correctSum will not be changed), and is
increased by 1 at the end of the loop:
if(sum != 24)
{
correctSum = false;
}
i++;
The third time the condition in the while statement is evaluated, i is 2. 2 is less than 7, and correctSum is true.
The condition evaluates to true, and the statements are to be run a third time.
while(i<codes.length && correctSum)
i is now 2, and code will be set to the third code, "3":
var code = codes[i];
The sum will now be 8+9+8 (Wednesday), which is 25.
var sum : int =
f("q2")[code].toNumber()+f("q3")[code].toNumber()+f("q4")[code].toNumber(
);
Now the condition in the if statement will yield true because 25 is not equal to 24. So this time correctSum will be
set to false.
if(sum != 24)
{
correctSum = false;
}
- 64 -
Forsta Confidential Forsta v2022 Scripting Manual
f("q2a")[code].toNumber()+f("q3a")[code].toNumber()+f("q4a")[code].toNumb
er(); var correctSum : Boolean = (sum == 24); //false if sum not 24,
true if sum is 24
i++;
}
while(i<codes.length && correctSum)
if(!correctSum)
{
RaiseError();
SetQuestionErrorMessage(LangIDs.en,"Please make sure that the total
number of hours for each day equals 24. Currently the sum for
"+f("q2a")[code].label()+" is "+sum+".");
}
- 65 -
Forsta v2022 Scripting Manual Forsta Confidential
The 3D grid contains 3 numeric list questions: q2 (sleep), q3 (work) and q4 (leisure). In addition we have a hidden
multi question error_rows which is used to set which rows have incorrect sums.
The following code is entered in the validation code field to evaluate the respondent's answers:
- 66 -
Forsta Confidential Forsta v2022 Scripting Manual
In scripts inside the loops you can refer to the questions as usual, e.g. f("types"). This will refer to that question in
the current iteration of the loop. However, if you need to refer to questions in the loops from scripts outside of the
loops, you have to specify which iteration you refer to.
For example, f("types","1") refers to the question called types in the iteration with code 1 within this loop. With
nested loops (like we have here), you specify the innermost iteration first, so f("rating","3","1") refers to the
rating question from the iteration with code "3" of the inner loop programs. For the outer loop channels it is the
iteration with code "1".
- 67 -
Forsta v2022 Scripting Manual Forsta Confidential
- 68 -
Forsta Confidential Forsta v2022 Scripting Manual
For each channel, the respondent answer what type of programs they watch on that channel, and then give a rating
for each program type for that channel in the rating question. Now we want to write a script that calculates an average
of these ratings for each channel. Here is the list of iterations in the channels question:
- 69 -
Forsta v2022 Scripting Manual Forsta Confidential
We set up a hidden numeric list question avg with the same list:
Now, after the loop we insert a script node to calculate these averages.
This script must run through all the items in the channels loop, and for each of them run through all the ratings
given in the programs loop:
- 70 -
Forsta Confidential Forsta v2022 Scripting Manual
- 71 -
Forsta v2022 Scripting Manual Forsta Confidential
10. Functions
Usually, when using scripts you reuse a lot of code. Instead of copying the entire code, you can define a function with
that code and call it when you need it.
Functions combine several operations under one name. This lets you streamline your code. You can write out a set of
statements and define the block of statements as a function and give it a name. Then the entire block of statements
can be executed by calling the function and passing in any information the function needs. If a function is given a
name that describes what it does, it will be easier to read and understand the code. It will hide details and make your
scripts more modularized.
You pass information to a function by enclosing the information in parentheses after the name of the function. Pieces
of information that are passed to a function are called arguments or parameters. Some functions do not take any
arguments at all while others take one or more arguments. In some functions, the number of arguments depends on
how you are using the function.
A function call is a statement used to invoke a function. Use the function name followed by parentheses containing the
arguments, if any, to do a function call:
FunctionName(p1,p2,...,pn)
You always have to use the parentheses, even if a function contains no arguments:
FunctionName()
A function may or may not return a value.
- 72 -
Forsta Confidential Forsta v2022 Scripting Manual
The question id of the numeric list question is percentage. In properties total digits is set to 3, scale to 0, and lower
and upper limit to 0 and 100, so that the system provided validation makes sure that only integers between 0 and 100
is allowed. To validate that the answer is equal to 100, you can use the Force sum of answers setting in the question
properties, or use the following code in the validation code field of the question:
var sum : int = Sum(f("percentage").values());
if(sum!=100)
{
RaiseError();
SetQuestionErrorMessage(LangIDs.en, "Your numbers add up to " + sum + ".
Please make sure that the numbers add up to 100.")
}
- 73 -
Forsta v2022 Scripting Manual Forsta Confidential
- 74 -
Forsta Confidential Forsta v2022 Scripting Manual
10.1.1.2. Count
Count( arguments )
Count returns the number of arguments. Valid argument types are numbers, strings, arrays or any kind of object. Use
comma to separate the arguments. An array will be split into its elements, so used on an array Count will return the
number of elements in the array.
- 75 -
Forsta v2022 Scripting Manual Forsta Confidential
If you want to find the number of items answered on all three questions combined, for example for use in a condition
to ask some further question(s) only if the respondent has answered more than one office, you can use the Count
function:
Count(f("officesa").categories(),f("officesb").categories(),f("officesc")
.categories()) > 1
If the respondent has picked 2 offices on q1, 1 office on q2 and 3 offices on q3, the result of this function call will be
the value 6 (2+1+3).
10.1.1.3. Average
Average( arguments )
Average returns the average (mean) of its arguments. Valid argument types are numbers, strings, arrays or any kind
of object. Use comma to separate the arguments.
- 76 -
Forsta Confidential Forsta v2022 Scripting Manual
f("sleep").set(Average(f("q2").values()))
f("work").set(Average(f("q3").values()))
f("leisure").set(Average(f("q4").values()))
(The 3D grid consisted of three numeric list questions, q2 for sleep, q3 for work and q4 for leisure). The hidden
question sleep for instance, will here be set to 8 since 56/7 is 8 (see Sum on page 72 for more information).
10.1.2. Range
Range has two alternatives:
InRange(arg,min,max)
InRange returns true if arg is within the range (min, max) (inclusive).
InRangeExcl(arg,min,max)
InRangeExcl returns true if arg is within the range (min, max) (exclusive).
If you wanted some questions to be sent only to people between the ages of 26 and 50, you could use a condition
with an expression as follows:
- 77 -
Forsta v2022 Scripting Manual Forsta Confidential
This function can for example be used to store the channel in a hidden single question channel by setting it in a
script node:
f("channel").set(GetSurveyChannel())
Another example is to use it inside a condition to ask certain questions only to web respondents:
A third example is to use it to display certain texts only when the interview is performed by an interviewer (CAPI or
CATI):
- 78 -
Forsta Confidential Forsta v2022 Scripting Manual
10.1.3.2. IsInProductionMode
IsInProductionMode()
IsInProductionMode() can be used to distinguish between running surveys in production mode or in quick test/external
quick test/test mode. It will return one of the following values:
10.1.3.3. GetRenderingMode
GetRenderingMode()
GetRenderingMode() can be used to determine whether desktop rendering, one of the mobile rendering modes (touch
or generic), is currently active in the survey. This function can for example be used in a condition if you would like
certain questions only to be presented in the desktop version of the survey. If responsive rendering is activated,
GetRenderingMode will return "responsive".
To get the mobile rendering modes (touch and generic), these modes must be active on the survey.
If you for example want to provide some questions only to users accessing a survey through the desktop rendering,
you can use the following expression in a condition, and then place those questions inside the Then branch:
GetRenderingMode() == "desktop"
10.1.3.4. GetContentType
GetContentType()
GetContentType()can be used to distinguish between surveys run as regular Web surveys or through a Flex extension
using the Survey Front End extension point, such as iPhone, Android and SMS surveys. It will return one of the
following values:
- 79 -
Forsta v2022 Scripting Manual Forsta Confidential
10.1.3.5. AdvancedWIFeaturesEnabled
AdvancedWIFeaturesEnabled()
AdvancedWIFeaturesEnabled() is used to determine whether the respondent’s browser supports Advanced WI
Features that require client side scripts, such as sliders, drag-n-drop ranking, images instead of radio-buttons/check-
boxes etc. It will return true if the respondent’s browser supports the advanced WI features, or false if not. It can for
example be used to display a different instruction text depending on whether or not respondents will have a question
displayed with the advanced WI interface.
This function is optimistic with regards to checking whether JavaScript is turned on or off in the browser. In other
words it will return true unless it is determined that JavaScript is turned off.
Note: This state can only be determined once the respondent has opened the first page of the survey. This
function must therefore be executed after the first page of the survey.
10.1.3.6. DynamicQuestionsEnabled
DynamicQuestionsEnabled()
DynamicQuestionsEnabled() is used to determine whether the respondent’s browser supports AJAX so that the
“Dynamic Questions” functionality can be used (see Dynamic Questions on page 11 for more information). It will
return true if the respondent’s browser supports AJAX, or false if not. It can for example be used for screening
respondents from a survey that have extensive usage of .this, or in a condition to provide an alternative path for
respondents, if they have a browser that does not support it. Unlike “Advanced WI Features”, no fallback (i.e.
alternative interface) exists for this functionality.
10.1.3.7. IsDynamicQuestionCallback
IsDynamicQuestionCallback()
IsDynamicQuestionCallback is used to determine whether the code is currently executed during a Dynamic Question
Callback, i.e. an Ajax update of one or more Dynamic Questions. This will be true if used within a question that has a
trigger, when one or more of the trigger questions is updated.
- 80 -
Forsta Confidential Forsta v2022 Scripting Manual
10.1.3.8. IsInlineSurveyCallback
IsInlineSurveyCallback()
IsInlineSurveyCallback is used to determine whether the survey is currently run as an inline survey.
For "regular" surveys, the response record is created when the respondent opens the first page of the survey (this is
the default). However for inline surveys, the response record is created when the respondent submits the first page of
the survey. This is done to reduce the amount of empty data records, since an inline survey may be placed within high
volume sites where only a small percentage of the visitors will submit a response.
It is therefore not possible to use the .set() method in a script within the first page to store responses when the survey
is running inline, because the data cannot be stored in the database since the database record does not yet exist.
Such scripts can only be run from the second page onwards.
If you need to retrieve values from the query string using Request (see Request on page 228 for more information)
and store in the database, you will have to do this on the second page. In inline mode the query string is preserved
when moving from the first to the second page.
If the survey is accessed both in inline mode and as a regular survey link, you do have to treat these modes
differently, and the IsInlineSurveyCallback function can be used for this. Let's say you send in a value site=1. At the
start of the survey you can add this script to fetch the value when the regular survey link is opened:
if(Request("site")!=null &&!IsInlineSurveyCallback())
{
f("site").set(Request("site"));
}
Before the second page, you can insert the following script to fetch the value when the survey is inline:
if(Request("site")!=null &&IsInlineSurveyCallback())
{
f("site").set(Request("site"));
}
10.1.3.9. CurrentForm
CurrentForm()
- 81 -
Forsta v2022 Scripting Manual Forsta Confidential
CurrentForm is used in validation code, masking and in response piping in a question's text fields (or in functions
called from validation code, masking and response piping) and returns the question ID (string) of the current question.
Used inside the validation code field of one of the questions inside a 3D grid, it will give the question id of that
question instead of the id of the 3D grid itself.
You can use this to write generic code that can be reused without having to change the question ID.
Note: For questions within a 3D-grid, CurrentForm works only in validation code scripts. For piping or other
scripts within a 3D-grid the evaluation depends on the execution context, so CurrentForm will not function
correctly.
10.1.3.10. GetRespondentUrl
GetRespondentUrl()
GetRespondentUrl(string qid)
GetRespondentUrl(string qid, params string[] loopQual)
GetRespondentUrl(string id, bool isCallBlock)
GetRespondentUrl(string id, bool isCallBlock, string parameters)
GetRespondentUrl(string id, bool isCallBlock, string parameters, params
string[]loopQual)
Where:
qid is a question id.
id is either a question id or a callbock id.
isCallBlock denotes whether the id is a question id or a callblock id.
parameters is a string to be passed into the survey in the url; the string can contain one or more parameters;
where more than one parameter is being used a semi-colon should be used as a separator.
loopQual is only applicable when the question id exists within one or more loops and the url is being used to
direct the respondent to a particular iteration.
GetRespondentUrl returns a URL that will allow the current interview to be entered at a specific point.
All of the parameters are optional. If they are not used the URL will, depending on the Survey Settings, take the user
either to the beginning of the interview or to the last question where they left off. But when they are used, they can
provide the following capabilities:
1. The respondent can be directed to the page of a particular question, and, if the question is inside one or more
loops, a particular loop iteration or iterations. The interview will then continue from that point.
2. The respondent can be directed to a particular callblock which, upon completion of the callblock, will finish the
interview.
3. The function can securely pass a text value or several text values into the start of the interview, that will then
be accessible via the UserParameters function.
GetRespondentUrl can be used for example to send an email to the respondent to allow him/her to re-access the
survey, or it can be presented inside the survey so that the respondent can copy it to return to the survey later.
To follow are some examples of different combinations of the optional parameters, and cases where they may be
used.
In this example,
GetRespondentUrl("q9")
will give a link that when opened, will open the survey for the current respondent on the page with q9, and then
continue through the interview. This could also be written as:
GetRespondentUrl("q9", false)
which will have the exact same effect.
In this example,
- 82 -
Forsta Confidential Forsta v2022 Scripting Manual
GetRespondentUrl("q7","3","2")
will give a link that when opened, will open the survey for the current respondent on the page with q7 for the iteration
with code "3" of l2 and the iteration with code "2" of l1.
In this example,
GetRespondentUrl("alert", true)
will give a link that when opened, will open the survey for the current respondent at the start of the call block named
“alert”. When the respondent finishes the callblock, after submitting the i40 info node, the interview will finish.
In this example,
GetRespondentUrl("q12", false, "alert=true")
will give a link that when opened, will open the survey for the current respondent on the page with q12, passing the
encrypted parameter named alert with a value of “true” (see the UserParameters function for details regarding
accessing the parameter).
In this example,
GetRespondentUrl("", false, "alert=true;state=red")
will give a link that when opened, will start from the beginning of the survey, passing the encrypted parameters named
“alert” and “state” with the values of “true” and “red” (see the UserParameters function for details regarding accessing
the parameter).
Note: When using GetRespondentUrl to pass several text values into the start of the interview, a semicolon ;
is used as a separator. If a ; is required as part of the parameter, it must be encoded.
The plus sign + must also be encoded if used as a parameter.
In this example,
GetRespondentUrl("cb1", true, "alert=true")
will give a link that when opened, will open the survey for the current respondent at the start of the call block named
“cb1”, passing the encrypted parameter named alert with a value of “true” (see the UserParameters function for details
regarding accessing the parameter). When the respondent finishes the callblock, the interview will finish.
Note: When GetRespondentUrl is used to access a callblock, the interview_start, interview_end and interview
status values are not updated during the callblock interviewing session. However, if the callblock contains a
STOP node then interview_end and interview status will be updated.
- 83 -
Forsta v2022 Scripting Manual Forsta Confidential
Important
GetRespondentUrl should not be used to start the interview at a question contained within a callblock as the
interview will fail when the respondent reaches the end of the callblock.
GetRespondentUrl access to a callblock will cause the interview to finish when the callblock is completed. It
is not designed to act as a scripted way to access a callblock.
GetRespondentUrl must not be used with CATI; use GetCatiRespondentUrl (see GetCatiRespondentUrl on
page 119 for more information).
In the example above, the survey setting “Encrypt System Request Parameters” is set. If this is disabled, the link will
have r=respid&s=sid instead of __sid__. GetRespondentUrl supports either option for respondent-specific URLs.
You can insert the respondent-specific URL in the text area of an info node as follows:
^GetRespondentUrl()^
The same functions can be used to email a personal link to a respondent (see SendMail on page 150 for more
information).
10.1.3.11. RedirectToRespondentUrl
RedirectToRespondentUrl()
Calling this function will result in an internal redirect to a specific location within the survey. This is similar to
Redirect(GetRespondentUrl()), but without resulting in seeing the new URL.
• If this function is used in an offline survey channel (not Web or CATI), it will be equivalent to calling
Redirect(GetRespondentUrl(…), true).
• The function has the same signature as GetRespondentUrl and all its features (such as redirect to CallBlock
and passing custom parameters) are supported (see GetRespondentUrl on page 82 for more information).
Note that a parameter must be passed. No parameters, that is RedirectToRespondentUrl() on its own, is not
supported.
10.1.3.12. CurrentID
CurrentID()
CurrentID returns the respid of the current respondent. Note that this does not necessarily apply to CAPI interviews;
CurrentID on the CAPI Console returns the CAPI local respondent ID.
- 84 -
Forsta Confidential Forsta v2022 Scripting Manual
You can use the remainder of respid divided by a number x to route respondents to x different parts of the
questionnaire in rotation. For example, if you have three sections A, B and C, you can create a pattern as:
respondent 1 would complete section B,
respondent 2 would complete section C,
respondent 3 would complete section A,
respondent 4 would complete section B,
respondent 5 would complete section C,
respondent 6 would complete section A,
etc.
This can be done by using the CurrentID() function and modulus / remainder. Depending on the result of
CurrentID()%3
the respondent is routed to the appropriate part of the questionnaire.
10.1.3.13. CurrentLang
CurrentLang()
CurrentLang returns the language code of the current language used (e.g. 9 for English). This can be used e.g. in
conditions if you want different routing for different languages. You can also use it to set hidden questions to use in
reporting if you want to report on the different languages.
10.1.3.14. CurrentPID
CurrentPID()
CurrentPID returns the project number of the survey (a number prefixed by p). This can for example be set in a
hidden variable to be used in data exports if you export from several surveys into a common format.
10.1.3.15. CurrentLoops
CurrentLoops()
CurrentLoops is used in validation code, masking and in response piping in a question's text fields (or in functions
called from validation code, masking and response piping) and returns the IDs of all loops that the current question is
located in. Calling CurrentLoops() as a function returns an array of strings containing the loop IDs, with the first (or
outer) loop at the start of the list. It will also return a list with one element in it so it is possible to get the loop ID with
CurrentLoops()[0] or CurrentLoops().ToString().
- 85 -
Forsta v2022 Scripting Manual Forsta Confidential
One scenario where it would be beneficial to update the respondent list is if you have a survey which the respondents
continuously update, and you want to keep sending new reminders to the respondents. If they change their email
address in the survey, you would like the respondent list updated with the new email address so that new reminders
are sent to the new email address.
GetRespondentValue(fieldname)
will return the value uploaded in the fieldname (string) column in the respondent list for the current respondent. If
the fieldname does not exist, null will be returned.
SetRespondentValue(fieldname,value)
will set fieldname (string) in the respondent list to value (string) for the current respondent. If fieldname does not
exist, nothing will happen. There are three system fields that can not be updated: rid, sid and rowguid. Attempting
to update any of these will give a script error.
Note: If a respondent re-enters the interview, interview_start is re-set, and similarly, if she or he reaches a
stop node or the end of the interview after re-entering a completed interview, the variable interview_end is
also re-set.
Two functions can be used to get the values of these timestamps in scripts
InterviewStart()
InterviewStart returns the respondent’s interview start time.
SetInterviewStart(date)
SetInterviewStart sets the respondent’s interview. The parameter date is optional. If it is not included,
interview_start will be set to current server time and date. If date is included, it can either be a JScript.NET
Date object or a .NET DateTime object.
InterviewEnd()
InterviewEnd returns the respondent's interview end time.
We will return to examples on how to use these functions later in the documentation (see InterviewStart and
InterviewEnd on page 188 for more information) where they are used together with the Date object.
- 86 -
Forsta Confidential Forsta v2022 Scripting Manual
There are also two functions available to set these timestamps. SetInterviewStart can be used for example
when you want interview start to be set after the screening questions of a survey instead of at the beginning of the
survey, and SetInterviewEnd can be used to set the interview end timestamp when a stop node is never reached
because of a redirect at the end of the survey (see Redirect on page 156 for more information).
SetInterviewStart() - sets the respondent’s interview start time to current server time and
date.
SetInterviewEnd() - sets the respondent's interview end time to current server time and date.
Status Code
Complete complete
Screened screened
Error error
If status is null, it means that the interview is incomplete. The "error" status is set if the interview terminates because
of an error in a script.
There are two functions that operate on status:
GetStatus()
GetStatus returns the current interview status.
SetStatus(status)
- 87 -
Forsta v2022 Scripting Manual Forsta Confidential
SetStatus can be used in a script to set the interview status, e.g. if you want respondents who have answered the
questionnaire up to a certain point to count as complete interviews, even though they do not answer all the remaining
questions. status is a string with the status value you want to set, i.e. "complete", "screened" or "quotafull".
SetStatus is very often used in combination with the Redirect function (see Redirect on page 156 for more
information).
The SetStatus function will just set the interview status, not the interview_end time stamp. interview_end is just set
when the end of the interview or a stop node is reached.
Note: The use of redirects, quotas, status-screened or other solutions with the principle purpose of avoiding
the survey "complete" status being reached by a respondent having offered a reasonable amount of
responses, is prohibited and will be regarded as an attempt to avoid transaction fee obligations to Forsta.
10.1.3.19. Forward
Forward()
Forward returns true if the respondent is moving forward through the questionnaire (has clicked on the forward
button), and false if the respondent is moving backward (has clicked on the back button). This can be used for code
that you only want to execute when the respondent moves in a particular direction.
There is no point in using this function in validation code, because validation code is only run when the respondent
moves forward in the questionnaire.
10.1.3.20. IsInRdgMode
IsInRdgMode()
IsInRdgMode returns true if the scripts are executed during a Random Data Generator run, false otherwise. You
may use this function to prevent some script code from being run when testing the surveys with the RDG.
10.1.3.21. SetRandomCategories
SetRandomCategories(number, qid)
SetRandomCategories can be used to randomly switch on the specified number of categories of the specified
question ID. Typically this would be used to randomly turn on number categories of a specific hidden qid. In the
example below, two categories of the hidden question q2 would be switched on.
SetRandomCategories(2, 'q2')
This function is only applicable for standard multi questions. It does not apply to multi questions with the Capture
Order property set.
(see Random on page 195 for more information)
10.1.3.22. TerminateLoop
TerminateLoop()
TerminateLoop is used inside of auto-increment loops. Auto-increment loops are only available for optimized database
projects. A TerminateLoop call is required to stop further iterations of the loop being created. Without this, the loop will
continuously create new loop iterations, and the respondent will never be able to finish the loop.
- 88 -
Forsta Confidential Forsta v2022 Scripting Manual
A script node containing a TerminateLoop function call is a mandatory requirement for an auto-increment loop
because an auto increment loop iteration requires some interactive content for the respondent (question, info node
etc.). If the loop contains nothing interactive, the interview will be terminated with an error status and an error
notification will be sent via email.
Note that the TerminateLoop function call must be placed at the end of the loop to have any effect.
In the following example the loopTermination script node contains the single function call TerminateLoop and is used
to prevent further iterations of the auto-increment loop based on the answer to the "continue" question.
TerminateLoop calls are only applicable to auto-increment loops; they are not applicable to, and have no effect on
loops based on normal answer lists or those based on table lookups.
10.1.3.24. UserParameters
UserParameters[paramName]
UserParameters can be used to access texts that are passed to the start of the interview using the
GetRespondentURL() function.
In this example,
UserParameters["alert"]
will give the value that the parameter named “alert” was set to when GetRespondentUrl was used to access the
survey.
Note: UserParameters can only be used on the first page that the respondent is directed to via
GetRespondentUrl. UserParmeters will return empty values if used later in the survey.
To access all parameter information UserParameters.Keys can be used. The Keys function returns a
NameValueCollection which can be iterated through.
In this example, a script function “ShowKeys()” has been created to display all parameter information:
- 89 -
Forsta v2022 Scripting Manual Forsta Confidential
function ShowKeys()
{
var str = "";
for(var x = new Enumerator(UserParameters.Keys); !x.atEnd();
x.moveNext())
{
var y = x.item();
str += "<br />" + y + " = " + UserParameters(y);
}
return str;
}
When piping the result of this function, for example using ^ShowKeys()^ in an interview initiated via
GetRespondentUrl("", false, "alert=true;state=red") the following the following will be displayed:
Note: Survey links in hitlists can have parameters added to the link. Two functions are available to receive the
value from the link; UserParameters and Request (see Request on page 228 for more information). The
function you must use depends on the link's “Link type” setting. UserParameters will only be able to retrieve
the value from the hitlist link when "Link type" in the Hitlist Field Properties page is set to "Encrypted URL
parameters". Refer to the separate Reportal User Guide for further details.
10.1.3.25. GetDeviceInfo
GetDeviceInfo()
GetDeviceInfo() is a scripting function that returns an object containing a variety of information regarding the type of
device that is being used by the respondent.
Note: The information returned is dependent on the rendering modes enabled for the survey. For example, if
mobile rendering channel is not enabled in Survey Settings then IsTablet will return False.
The object returned contains the properties described in the following table:
- 90 -
Forsta Confidential Forsta v2022 Scripting Manual
ScreenResolution String “600|400” or “0|0” The screen resolution of the device being used
width|height or “0|0” if unknown.
DeviceType String "Desktop", "Touch", The device type in use.
"Generic"
DeviceType.toString() String "Desktop", "Touch", The device type in use.
"Generic"
Note: ScreenResolution will only be available if Smartphone rendering mode is enabled and the device is
either a touch or tablet device.
Note: The definition of "Tablet" is a device with a user agent string conforming to the
UserAgentRegExTouchDevice expression from System Configuration that also has at least one screen
dimension exceeding 650px.
When only Desktop mode is enabled, the screen resolution check is not performed so IsTablet will always return false.
Important
Screen dimension is often considered to be the actual screen resolution that is advertised on a phone’s
specification sheet (i.e. the screen.width and screen.height * the device pixel ratio). If you are using and
relying on the GetDeviceInfo().ScreenResolution information in your survey, be aware that Forsta uses the
viewport’s width and height (that is window.innerWidth and window.innerHeight). Forsta also uses the CSS
Interpretation (the resolution / the device pixel ratio) divided again by the device pixel ratio. These are the
numbers that are returned for GetDeviceInfo().ScreenResolution, and the numbers used to determine tablet.
- 91 -
Forsta v2022 Scripting Manual Forsta Confidential
Important
Be aware that although iPad is classified as a tablet device, iPad is included in the desktop regex (the
UserAgentRegExDesktop expression from System Configuration) that is configured for Forsta. Therefore if a
respondent is taking a survey on an iPad device, IsTablet and IsTouch will never return true; it only gets as
far as the first check (the user agent string) and returns false.
10.1.3.26. GetQuestionIds
GetQuestionIds is used to return a string array of question IDs based on specific filters provided.
GetQuestionIds(questionTypes: String[], variableTypes: String[], loopId:
String)
GetQuestionIds(includeInteractiveQuestions: Boolean,
includeNonInteractiveQuestions: Boolean, loopId: String)
Where:
questionTypes is a string array that filters and lists questions which are of a specific type only. The types
are (case insensitive): "single", "multi", "grid", "ranking", "open text list", "numeric list", "open", "numeric",
"date", "geolocation", "imageupload", "multigrid" and "3dgrid".
variableTypes is a string array which filters and lists questions which are of a variable type, the types are
(case insensitive): "normal", "panelvisible", "hidden", "background", "recoded" and "recoding“.
loopId filters and lists questions inside the specified loop only (not recursive).
includeInteractiveQuestions if set true will filter and list all questions that have normal or panel visible
variable types.
includeNonInteractiveQuestions if set true will filter and list all questions that have hidden,
background, recoded and recoding variable types.
Note that only root nodes of multigrids and 3dgrids are listed. It is possible to get title, text and instruction of a
multigrid or a 3dgrid using f(g1).text() or .label() or .instruction().
In this example,
GetQuestionIds(true, false)
will return a string array of all interactive questions in the survey.
In this example,
var questionsTypesIncluded : String[] = ["open", "numeric"];
f("myQuestions").set(GetQuestionIds(questionsTypesIncluded).toString());
will set the ”myQuestions” answer to be a comma-separated list of all open text and numeric questions in the survey.
10.1.3.27. Get3DGridQuestionIds
Get3DGridQuestionIds is used to return a string array of the questions inside a specific 3DGrid, and will also return
the row question ids of a multigrid when the multigrid id is used as the function argument.
Get3DGridQuestionIds(gridId: String)
Where:
gridId is the question ID of a 3Dgrid.
In this example,
Get3DGridQuestionIds("g1").toString()
will return a comma-separated list of all question IDs inside the 3DGrid “g1”.
As a Multigrid object is a transposed 3D Grid, this function can also be used to retrieve the Question (row) ids of a
multigrid.
Note: When the Multigrid or 3D Grid contains an Other - Specify answer option then the form name will be
returned in the array as the first element.
- 92 -
Forsta Confidential Forsta v2022 Scripting Manual
10.1.3.28. GetSurveyPackageVersion
GetSurveyPackageVersion()
The GetSurveyPackageVersion function can be used to return the internal survey package number for the survey
currently being used. This information can be useful when ensuring that a specific version of the survey is being used.
10.1.3.29. GetCompanyId
GetCompanyId()
GetCompanyId can be used to get the ID of the company that this survey belongs to. The CompanyId is an int.
10.1.3.30. GetSurveyName
GetSurveyName()
GetSurveyName can be used to get the name of the current survey, as a string value.
10.1.3.31. GetResponseId
GetResponseId()
This gives the response ID of the current interview record. Use example: The text below could be added to a text field.
The Response ID allocated to this interview is: ^GetResponseId()^
This function can also be used in scripting.
See also CurrentID() (see CurrentID on page 84 for more information).
10.1.3.32. GetLanguageCodes
GetLanguageCodes()
GetLanguageCodes() can be used to return a set of language IDs that exist for the current survey. This can be used
to check if a specific language code/s is valid in a survey, or it can be used as a mask on a question, based on the
available languages. In the example below the function is used to return a set of available languages, then based on
the language codes and the answer codes, the answer list will be filtered to only display the languages available in
this survey.
- 93 -
Forsta v2022 Scripting Manual Forsta Confidential
10.1.3.33. FormExists
FormExists(string qid)
FormExists() is used to check if a specific form exists in the current survey. The function returns true if the form exists
in the survey, false if it does not. For example the script below checks if q1 exists:
var qid = "q1";
var questionExists = FormExists(qid);
This can be used in scripting to ensure that a form actually exists, before referencing it.
- 94 -
Forsta Confidential Forsta v2022 Scripting Manual
10.1.4.2. RequestIP
RequestIP()
Returns the IP address of the respondent as a string on quad IP form. This can for example be used to set the IP
address of a respondent in an open text question.
Note: Recording the respondents' IP addresses may be in conflict with respondents' privacy. Responsibility
for ensuring respondents' privacy resides with the Forsta clients. Forsta recommends following ESOMAR
guidelines, see www.esomar.org.
If you have an open survey, but want to limit the respondents from answering more than once, you might want to
record the IP address and remove responses from repeat IP addresses. However, this probably will not give the
desired effect, because:
Note: The Capture Order property is only available in surveys using the Optimized database.
- 95 -
Forsta v2022 Scripting Manual Forsta Confidential
10.1.5.1. First
This function is used to return the first category selected for multi choice questions with the capture order property, or
the category ranked as 1st for a ranking question.
First(qid)
First returns the code or label, depending on the context, of the first selected or ranked as number 1 answer category
for the specified question ID qid. Label will be returned in text piping mode (within ^s), code elsewhere.
This function can only be used on ranking questions and multi's that have the capture order property enabled. It is not
applicable to other multis.
If these responses were given in the order ITV1, BBC1, Channel 5, we would get the following result from using
First():
- 96 -
Forsta Confidential Forsta v2022 Scripting Manual
10.1.5.2. Nth
This function returns the nth category selected for a multi choice question with the capture order property, or the
category ranked as the nth for a ranking question.
Nth(qid,position)
Nth returns the code or label, depending on the context, of the answer category in the position specified for the
specified question ID. Label will be returned in text piping mode (within ^s), code elsewhere.
Nth(“q1”,1) will return the same value as First(“q1”). This function can only be used on ranking questions or multi's that
have the capture order property enabled. It is not applicable to other multis.
If these responses were given in the order ITV1, BBC1, Channel 5, we would get the following result by using Nth():
- 97 -
Forsta v2022 Scripting Manual Forsta Confidential
10.1.5.3. AnswerOrder
This function is used to return an array of codes in the order selected for a multi choice question, or in the order
ranked for a ranking question.
AnswerOrder(qid)
AnswerOrder returns the codes of the answers supplied in the order they were selected or ranked for the specified
question ID. The primary purpose of this function is to make it easy for users to retrieve the selected answer codes
without having to use the Nth() function and loop through the answer list multiple times, which would result in poor
script and server performance in the event of a very long answer list.
This function can only be used on ranking questions or multi's that have the capture order property enabled, it is not
applicable to other multis.
10.1.5.4. Setting Variables for Nth Mentioned / Ranked for Reporting Purposes
If you have a ranking question or a capture order multi, you will easily be able to report on which ranks/order of
mention each answer got. However, if you want to report on answers per rank/order of mention, you will save some
recoding work by creating a set of hidden single variables for each rank/order of mention, that have the same answer
list as the multi.
In this example we have a question “cars”, in which the respondents are asked to rank up to three of their favorite
cars. The three hidden single questions rank1, rank2 and rank3, are set up with the same answer list as the multi, and
will be used to store the car selected as number 1, 2 and 3.
The following script will set the single questions based on the responses to the ranking question:
var ordered = AnswerOrder("cars");
for(var i=0;i<ordered.length;i++)
{
f("rank"+(i+1)).set(ordered[i]);
}
- 98 -
Forsta Confidential Forsta v2022 Scripting Manual
Note: The schema and table IDs being referenced must be part of the survey, either as an answer list or loop
list. If a table is referenced that is not used in the survey, the function will fail at run-time.
This function can be used to retrieve values from additional columns that are associated with answers for a table
lookup list defined within database designer. For example a table lookup list may be defined in the following way:
The database schema “Basic_Cars” (schema ID 805) contains table “car_list” (table ID 1543) with a list of
cars, each containing their own unique string key value. Additionally there are 2 columns “cost” and “spec”
containing background information relating to the specific cars.
During the survey, the author would like to pipe in the answer to “cost” and store the value of “spec” in a hidden
question. If table lookup question named car_owned is based on this table lookup as follows:
Piping in the value of the cost of the selected car can be achieved using the following syntax:
^GetDBColumnValue(805, 1543, f('car_owned').get(), 'cost')^
as shown here:
- 99 -
Forsta v2022 Scripting Manual Forsta Confidential
Similarly, if the value for spec for the English language (language ID is 9) is to be stored in the hidden question
c_spec, the following script syntax can be used:
f('c_spec').set(GetDBColumnValue(805, 1543, f('car_owned').get(), 'spec',
9))
If the keyID value is supplied explicitly, this must be contained within quotes as this is a string value. For example, to
store the value of keyed 7, the following syntax can be used:
f('c_spec').set(GetDBColumnValue(805, 1543, '7', 'spec', 9))
Note: The GetDBColumnValue() function is not executed during a Random Data Generator run. In this case
the value returned will be empty.
Note: The GetAdditionalColumnValue method is described here (see GetAdditionalColumnValue on page 46
for more information).
10.1.7. Offline Mobile App Specific Functions - CAPI and AskMe App
CAPI (Computer-Assisted Personal Interviewing) and AskMe App (Self-Completion) are Forsta add-ons.
CAPI App is designed for face-to-face interviewer led survey intercepts using Android, iOS or Windows devices.
AskMe App is designed for self-complete where the respondent completes the surveys on their own personal device.
Supported platforms are Android and iOS.
For more information on specific platform support for CAPI and AskMe App, refer to the Forsta System Requirements
document on Forsta.com
Note: The JavaScript Survey Engine must be enabled to use these functions. To enable this, check the "Use
JavaScript scripting engine" survey setting.
10.1.7.1.1. GetDeviceUniqueId
Return the unique ID for the device being used. Note that the identifier is retained/persisted even if the app is
uninstalled.
GetDeviceUniqueId()
Alternatively, see GetOfflineInfo() for related information.
10.1.7.1.2. GetOfflineInfo
Use GetOfflineInfo() function, to access app and device information:
- 100 -
Forsta Confidential Forsta v2022 Scripting Manual
• DeviceLanguageId returns the Forsta language code determined by the device locale (e.g. fr-be = 2060
French Belgium). Note that this is the derived Forsta language code and may not be the language set for a
survey if the survey does not contain the same language. To determine if the survey contains the same
language, you are recommended to use CurrentLang() to determine if the target device language is supported
by the current survey.
• DeviceLocale returns the device country code exposed by the operating system (e.g. "be").
• DeviceModel - returns the model information exposed by the operating system.
• DeviceOs returns the operating system the device is using.
• DeviceOsVersion returns the operating system version.
• DeviceUniqueId returns the device's unique id code.
• DeviceName returns the name of the device (if exposed by the operating system).
Examples of use:
var lvl = GetOfflineInfo().AppVersion
var lvl = GetOfflineInfo().DeviceOs
var lvl = GetOfflineInfo().DeviceOsVersion
var lvl = GetOfflineInfo().BatteryLevel
var lvl = GetOfflineInfo().DeviceModel
var lvl = GetOfflineInfo().DeviceUniqueId
var lvl = GetOfflineInfo().DeviceName
Example usage
Here we are setting/getting a counter for the survey local variable (just referencing the value of QID q1):
SetSurveyDeviceVariable("diaryIteration", f('q1'));
GetSurveyDeviceVariable('diaryIteration')
And here we are setting/getting the user's name from a user-level local variable (just referencing the value of QID
fullname):
SetUserDeviceVariable("AskMeUsername", f('fullName'));
GetUserDeviceVariable('AskMeUsername')
- 101 -
Forsta v2022 Scripting Manual Forsta Confidential
Note: You cannot set the value for an Audio Capture question.
startAudioCapture
Starts the audio recording.
f(qID).startAudioCapture()
Where qID is an audio capture question contained anywhere within the survey (it is recommend to set this as hidden).
Note: If this is the first time audio recordings have been initiated by the application on the device, the user
may be prompted to allow access to the microphone. This could be confusing to the user as it may not be
obvious why this is being requested. It may therefore be advantageous to include an Information node to
explain what is happening and why.
stopAudioCapture
Stops the audio recording.
f(qID).stopAudioCapture()
The audio recording will be saved to the audio capture question referenced by qID.
Note that the following conditions will also cause the recording to be stopped:
Note: You cannot set the value for an Audio Capture question, and the Min property will be ignored.
10.1.7.1.5. openVideoInApp
Function to play a video using the device built-in video player triggered by a button or other event:
openVideoInApp()
Example question text HTML source:
<a onclick="openVideoInApp('/isa/BDJPDAVIOEQJR/p5165/demo.mp4');return
false;">Play Video</a>
Alternatively, videos can be presented using the <video> HTML tag:
<video playsinline width="100%" controls preload="none">
<source src="/isa/BDJPDAVIOEQJR/p5165/demo.mp4" type="video/mp4" />
</video>
Video files can be added to the File Library making them available for offline viewing.
Device specific behavior for playsinline option (e.g. within same survey view):
- 102 -
Forsta Confidential Forsta v2022 Scripting Manual
10.1.7.1.6. openAudioinApp
This function plays an audio file:
openAudioInApp(url,openExternalPlayer)
where:
10.1.7.2.1. PostponeInterview
PostponeInterview(“description”, removeOnSync)
This function can be used to postpone a survey automatically when an interviewer reaches a specific point in the
survey path and the interview is to be considered as postponed. In CAPI App this function is equivalent to the
interviewer going to the in-survey menu and selecting Postpone Interview.
The description parameter is optional; if it is not supplied, the following default text will be recorded – "Interview
postponed via script".
The removeOnSync parameter is an optional boolean value (default false). If it is supplied, the description parameter
is required. The removeOnSync parameter will result in the survey being removed on the next sync that is performed.
This provides a way to allow respondents to be completed across many different CAPI devices or even web. For
example, in the situation where a survey needs to be started on Device A, postponed, re-assigned to Device B,
postponed, re-assigned back to Device A, the latest respondent will not be downloaded on Device A in normal
situations as the respondent on Device A is retained after being uploaded. By setting removeOnSync to true, this will
allow the respondent on Device A to be removed allowing a new/updated respondent to be downloaded at a later
time.
10.1.7.2.2. GetCapiInterviewerName
GetCapiInterviewerName()
GetCapiInterviewerName returns the username of the currently logged on interviewer.
10.1.7.2.3. GetCapiDeviceOs
GetCapiDeviceOs()
GetCapiDeviceOs() returns the operating system used by the device. The returned string values can be:
Windows
Android
iOS
If the device is not set up for CAPI, then nothing is returned.
Alernatively, see GetOfflineInfo() for related information.
- 103 -
Forsta v2022 Scripting Manual Forsta Confidential
10.1.7.2.4. GetCapiBatteryLevel
GetCapiBatteryLevel()
GetCapiBatteryLevel() returns the current percentage level for the CAPI device battery as a numeric value. This
function only applies to Android and iOS CAPI apps; the Windows CAPI console, and any other modes such as a
CATI or web survey, will always return a value of 100.
Alernatively, see GetOfflineInfo() for related information.
10.1.7.3. CapiAssignRespondent
CapiAssignRespondent(“interviewername”)
This function can be used to allow CAPI assignments to be added to the current respondent, meaning this interview
will then be available for the CAPI interviewer to work on in the CAPI channel.
If the CAPI channel is not enabled for the survey, or if an invalid CAPI interviewer name is provided, the survey will
continue and the survey author will receive an error email.
If the record is already assigned to another interviewer, calling this function will replace the existing assignment with
the new assignment.
Note: This function is intended to be initiated while running in CAWI to facilitate transition of an online survey
to an offline survey in CAPI.
10.1.7.4. CapiUnassignRespondent
CapiUnassignRespondent()
This function can be used to remove an interviewer assignment from this respondent.
If the CAPI channel is not enabled for the survey, the survey will continue and the survey author will receive an error
email.
Note: This function is intended to be initiated while running in CAWI to facilitate transition of an online survey
to an offline survey in CAPI.
- 104 -
Forsta Confidential Forsta v2022 Scripting Manual
GetOfflineSurveyDescription()
SetOfflineSurveyDescription(description)
- 105 -
Forsta v2022 Scripting Manual Forsta Confidential
• The number of iOS concurrent notifications is limited due to a limitation in the OS. It may be possible to
schedule up to 64, but this number may be significantly lower depending on the surveys that are loaded in the
app.
• Major device or OS upgrades may discard set alarms.
SetSurveyNotification
SetSurveyNotification(reminderName, displayLabel, notificationTimestamp)
SetAppNotification
SetAppNotification(reminderName, displayLabel, notificationTimestamp)
- 106 -
Forsta Confidential Forsta v2022 Scripting Manual
In contrast to SetSurveyNotifications, this does not start a specific survey. This allows for situations where the user
may need to continue where they left off providing an opportunity to resume.
Calling the function with the same reminderName overwrites previous settings.
SetRepeatingSurveyNotification
SetRepeatingSurveyNotification(reminderId, displayLabel, minuteOfHour,
hourOfDay, dayOfWeek)
CancelSurveyNotification
CancelSurveyNotification(reminderId)
CancelSurveyNotifications
CancelSurveyNotifications()
This function cancels all notifications set in this survey.
GetLastSurveyNotificationDate
GetLastSurveyNotificationDate()
This function returns the timestamp of the last time a notification was displayed to the user from this survey based on
the set notifications.
It is important to understand that this returns the expected last notification timestamp, not the timestamp of the last
actual display of a notification.
Example: Provide time window for when survey can be completed
- 107 -
Forsta v2022 Scripting Manual Forsta Confidential
// ensure the user started the survey within 15 minutes of receiving the
survey reminder
var d = new Date();
d.setMinutes(d.getMinutes() - 15);
if( GetLastSurveyNotificationDate() < d )
{
//show an informational question - "Sorry, you didn't start the survey in
time. You will get another chance tomorrow"
}
Example: Check if user has notifications enabled for app
if(!IsAppNotificationPermissionEnabled())
{
// Show informational node to ask user to enable notifications
IsAppNotificationEnabled
IsAppNotificationEnabled()
This function checks if the user has enabled notification permissions for the app.
ShowAppNotificationSettingsDialog
ShowAppNotificationSettingsDialog()
This function displays the notification permissions screen to allow the user to change the setting for the app.
10.1.7.5.3. GetAdvertisingInfo
Use GetOfflineInfo().GetAdvertisingInfo() function, to access device Advertising information:
• .AdvertisingID returns the device advertisingID where possible. This is a helper function without needing to
perform platform specific checks.
• .GAID returns the Google Advertising ID (Android only, iOS returns null).
• .IFV returns the Apple Identifer for Vendors (iOS only, Android returns null).
• .IFA returns the Apple Identifer for Advertisers (iOS only, Android returns null).
• .IsLimitAdTrackingEnabled returns true if user has enabled option to limit ad tracking (Android only, iOS
returns null).
• .IsAdvertisingTrackingEnabled returns true if user has enabled option to limit ad tracking (iOS only, Android
returns null).
Examples of use:
var adId = GetOfflineInfo().GetAdvertisingInfo().AdvertisingID
var gaid = GetOfflineInfo().GetAdvertisingInfo().GAID
var ifv = GetOfflineInfo().GetAdvertisingInfo().IFV
var ifa = GetOfflineInfo().GetAdvertisingInfo().IFA
var isl = GetOfflineInfo().GetAdvertisingInfo().IsLimitAdTrackingEnabled
var isl =
GetOfflineInfo().GetAdvertisingInfo().IsAdvertisingTrackingEnabled
10.1.7.5.4. notifyNativeApp
This function is available for custom branded AskMe applications.
notifyNativeApp(provider, eventName, customData)
- 108 -
Forsta Confidential Forsta v2022 Scripting Manual
10.1.8.1. Redo
Redo() forces a redo of a specific question:
Redo('qid')
where qid is the question ID of the question that is to be re-done.
Redo can be used together with SetErrorMessage to provide a redo-context sensitive error message (this can be
defined per language). Example:
Redo(‘q1’)
SetErrorMessage(LangIDs.en, 'Error Message')
Considerations regarding use of Redo:
• Redo can only be used for surveys that use the optimized database format.
• Redo can only be used in CATI, CAPI or AskMe survey channels. If, however, a survey is running in the CATI
channel then Redo is available for CAWI interviewing also. No error will be reported at launch time if the
survey contains an 'unsupported' Redo , instead the survey will produce an internal error at runtime.
• The question id has to be a question that the interviewer has seen before (i.e. a question that has already
been processed).
• The question id can be a question inside a callblock. If the callblock has been called multiple times, the the
most recent call the callblock will be chosen.
• The question id can be a question inside a loop. The first iteration of the loop is chosen.
• The function is supported by quick test.
Invoking the Redo() will cause the engine to return to the specified question ID. Having then answered this question
the engine will fast forward back to the script that invoked the Redo. If during fast forward the interview cannot
progress due to a change in the interview path or due to some validation the interview will continue from that point.
Important
When fast forwarding through the project, the Redo() WILL be re-executed. Therefore an example such as:
q1 - Gender question
Script: Redo('q1')
will produce a loop, repeating q1 over and over again. This is intentional behavior. It is the survey author's
responsibility to use the function in a way that takes this into account. The Redo is intended to be based on a
particular condition that must be resolved to bypass the Redo, so it will typically be placed within a condition
or similar.
- 109 -
Forsta v2022 Scripting Manual Forsta Confidential
Similarly the telephone number can be set inside a script node in Survey Designer as follows:
SetTelephoneNumber(value)
Where value is the (string) value that is to be assigned as the respondent's telephone number.
- 110 -
Forsta Confidential Forsta v2022 Scripting Manual
An example of retrieving the value of the respondent's telephone number extension may be as part of an initial contact
screen, such as the info node below:
Similarly the telephone number extension can be set inside a script node inSurvey Designer as follows:
SetExtensionNumber(value)
Where value is the (string) value that is to be assigned as the respondent's telephone number extension.
- 111 -
Forsta v2022 Scripting Manual Forsta Confidential
Note: On a supporting dialer the system field for ‘ExtensionNumber’ will be sent to the dialer as a call
property to specify the desired Caller ID (CLID). This means that individual CLIDs can be set by supplying the
desired values in a sample file (using a column headed ‘ExtensionNumber’). Contact support to check if your
system supports this functionality.
The first ‘ID’ column corresponds to the respondent's time zone Id.
GetTimeZoneId()
will return the numeric Id stored for the current respondent.
It is also possible to define the time zone for the respondent; this can be achieved using a script node. Here
SetTimeZoneId(value)
can be used to set the value of the time zone, where value is an valid integer time zone Id value. In the following
example the respondent's time zone is changed to time zone Id 3 (GMT+1).
- 112 -
Forsta Confidential Forsta v2022 Scripting Manual
GetExtendedStatus()
will return the value of the current interview's extended status value (integer). If no value is set 0 will be returned.
A typical example of where this may be used is in the End block of a CATI interview. When an interviewer terminates
the interview during an interview, the interview is immediately given a GetExtendedStatus() value of 6. The End block
can then be used to react to this termination. In the example below, for interview terminations the type of termination
is sub-classified by a termination question and then the interview is further dispositioned to a new extended status
value depending on the termination type:
It is also possible to define the extended status value for an interview. This can be achieved using a script node. Here,
SetExtendedStatus(value)
can be used to set the value of the extended status, where 'value' is a valid integer extended status value; an integer
between 1 and 120.
The initial contact screen that is used to record the call-outcome of the call demonstrates the use of this function. Here
we can see the Dial_Outcome question where the call-outcome is recorded:
- 113 -
Forsta v2022 Scripting Manual Forsta Confidential
The codes here correspond to the extended status code list within the CATI supervisor. Therefore the script node s1
is used to disposition the interview with a SetExtendedStatus() value corresponding to the code for the selected
category in the Dial_Outcome question.
10.1.8.6. GetLastInterviewStart
GetLastInterviewStart()
GetLastInterviewStart returns the date/time of the previous call attempt made to this respondent.
10.1.8.7. GetLastChannelId
GetLastChannelId()
GetLastChannelId returns the ID (integer) corresponding to the channel used during the last interview attempt
ID Channel
0 None
1 Web
2 CAPI
4 Random Data
Generator
8 CATI
10.1.8.8. GetCatiInterviewerId
GetCatiInterviewerId()
GetCatiInterviewerId returns the ID corresponding to the CATI interviewer as defined by the ID column in the CATI
interviewer list in the CATI supervisor.
- 114 -
Forsta Confidential Forsta v2022 Scripting Manual
10.1.8.9. GetCallAttemptCount
GetCallAttemptCount()
The GetCallAttemptCount function is used to return the number call attempts made to this respondent. For example
the following info node would display the number of attempts made:
10.1.8.10. GetTotalAttempts
GetTotalAttempts()
The GetTotalAttempts function is used to return the number of attempts made to this respondent in either CATI or
Web interview modes. For example,
^GetTotalAttempts()^
used in an info node would display the total number of attempts made to this respondent in either CATI or Web
interviewing.
Note: This function is not available for CAPI interviewing and is only available for surveys that have the CATI
channel enabled.
10.1.8.12. GetDialStatus
A function exists that returns the outcome of a dial attempt made by the dialer (when a company has the CATI
telephony add on enabled). The GetDialStatus() function call will return a numeric value corresponding to the outcome
list below.
- 115 -
Forsta v2022 Scripting Manual Forsta Confidential
Typically this would then be used to control either continuing the call or finishing the interview, as shown in the
screens below:
- 116 -
Forsta Confidential Forsta v2022 Scripting Manual
Note: The GetDialStatus() function should not be called before the dial command has been issued for this
interview. If it is, it will return the last DialStatus value from the previous call, or a “0” if it is the first call. For
surveys using more than 1 dial mode (for example a predictively dialed survey that has preview in predictive
calls), ensure that appropriate logic surrounds the function such that it is only retrieved once the dial
command has been issued.
10.1.8.13. GetDialType
GetDialType()
GetDialType() can be used to obtain information about how the current phone interview was dialed, either manually
(by hand) or automatically (using an autodialer).
10.1.8.14. GetTotalDuration
GetTotalDuration()
The GetTotalDuration function is used to return the number of seconds spent interviewing cumulatively across all
interview attempts. For example the follow info node would display the amount of time spent on this interview across
all interview attempts:
10.1.8.15. GetCatiInterviewerName
GetCatiInterviewerName()
- 117 -
Forsta v2022 Scripting Manual Forsta Confidential
GetCatiInterviewerName returns the username of the currently logged on interviewer. This is the Login column in
the CATI interviewer list in the CATI supervisor. This is typically used during the initial greeting with the respondent,
for example as follows:
10.1.8.16. GetCatiAppointmentTime
GetCatiAppointmentTime()
GetCatiAppointmentTime returns the time (in local respondent time) for the CATI appointment that has just been
made. This is designed to be used in the Exit block at the end of the current interview only. For example the following
survey would display the time and also capture it to a hidden variable to be used at the start of a subsequent call. An
example of such a survey is:
This is then piped in during the Start block in the i3 info node.
- 118 -
Forsta Confidential Forsta v2022 Scripting Manual
10.1.8.17. GetCatiRespondentUrl
This is GetRespondentUrl for CATI.
Using a redirect inside a CATI survey that jumps to a specific question in the survey (for example
Redirect(GetRespondentUrl("q1")) results in the interview continuing in Web mode with a number of negative
implications because GetRespondentUrl is not supported in CATI. The GetCatiRespondentUrl() function has the same
signatures as GetRespondentUrl() and is intended for use in CATI interviewing to safely jump to a specific question.
The same rules apply as for GetRespondentUrl() (see GetRespondentUrl on page 82 for more information).
Note: The GetCatiRespondentUrl() function must ONLY be used in conjunction with redirects to questions
inside of the same CATI survey. The GetCatiRespondentUrl() function only applies in the CATI interviewing
mode. If it is used in other modes it behaves like GetRespodnentUrl().
10.1.8.18. GetCatiStationId
GetCatiStationId()
GetCatiStationId() can be used to obtain the CATI interviewer station ID of the device being used to conduct the
current interview. Each workstation in a CATI call center has its own workstation label (Station ID) – specified as a
string when making a fresh console installation.
1. TCI and ProTS: whole interview recording and sectional recording are available. However it is not possible to
have concurrent whole interview recording and sectional recording; if whole interview recording is enabled
when a StartVoiceRecording() function call is made the whole interview recording will be stopped
2. Open Dialler API diallers: whole interview recording and sectional recording are available, even concurrently.
Whole interview recording cannot be controlled with scripting functions – for example
StopVoiceRecording(‘WholeInterview’) or StopVoiceRecording(‘Both’) - unless ‘Enable whole interview audio
recording’ is checked in Survey Designer > Survey Settings > CATI - Telephone.
If only sectional recording is required, ‘Enable whole interview audio recording’ must be unchecked.
10.1.8.20. fr
fr()
Note: This function is obsolete; you should use GetRespondentValue() instead (see GetRespondentValue and
SetRespondentValue on page 85 for more information).
This function is only available in survey scheduling within the CATI supervisor. The function can be used to reference
the value of CATI replicated background variables in a scheduling script. Only variables with the "Available as CATI
filter" question-level property can be referenced. The following demonstrates how a filter can be used when referring
to the value of the CATI replicated variable named gender:
- 119 -
Forsta v2022 Scripting Manual Forsta Confidential
10.1.8.21. IsCallExpired
IsCallExpired()
This function is only available inside of survey scheduling inside of the CATI supervisor. CATI scheduling is invoked
when a call expired event occurs. Typically, this would be due to an appointment expiry timeout being reached. During
scheduling execution the IsCallExpired function returns true if scheduling has been invoked due to a call expiry event.
This allows a new call to be scheduled in this scenario, here the actions are to remove assignment locking, set the call
priority to be 2000 and set the time to call to be now.
10.1.8.22. AddToCatiBlacklist
AddToCatiBlacklist()
This function is available in Survey Designer for CATI-enabled projects. When this function is called, the current
respondent’s telephone number (contained within the respondent data variable named TelephoneNumber) will be
added to the company's telephone blacklist. The telephone blacklist can be managed from the CATI Supervisor, from
the Resources tab > Telephone Blacklist item. When telephone blacklist support is enabled at the survey level in
Survey Designer, any attempt to call one of the blacklisted numbers will not be processed and the respondent
extended status will automatically be changed to 'Blacklist'. Duplicate numbers or numbers containing spaces or
special characters such as ( ) + # - will not be added to the list. Refer to the separate CATI Supervisor User Guide for
further information on creating and maintaining a telephone blacklist.
10.1.8.23. GetParamValue
GetParamValue(value)
This function is only available in survey scheduling in the CATI supervisor. If the scheduling script contains some
defined parameters then these parameters can be referenced in filters in scheduling. In this example a scheduling
parameter named TimeFrame exists, where ID is 1.
- 120 -
Forsta Confidential Forsta v2022 Scripting Manual
To refer to these parameters, use the GetParamValue(value) function where you can either pass the
GetParamValue("ParameterName") or GetParamValue(ParameterId) to reference by name or ID. For example,
GetParamValue(“TimeFrame”) or GetParamValue(1). The example below shows this being used in the filter for the
Busy call outcomes.
10.1.8.24. StartCATIAudioPlayback
StartCatiAudioPlayback (“filename”,[auto_start])
This function is only applicable for CATI-enabled projects, in the CATI channel and when working with a supported
Dialer. When this function is called a command is sent to the dialer to play the specified sound file. The function can
be used in any interactive text that will be displayed to the CATI interviewer; typically this would be a question relating
to the sound file being played. This function should not be used inside of non-interactive nodes such as script nodes
or hidden questions as this will result in nothing being played to the CATI interviewer.
The parameters are the filename (excluding path) of the .WAV file to be played and optionally a Boolean for
automatically starting the sound file playback when the function is invoked. The auto_start parameter determines
whether the sound file should immediately start playing when the function is invoked, if this is not specified the default
value is false (or 0) meaning the file will not start playing immediately. Example of usage is as follows:
In this example, the CATI interviewer console will activate the sound playback buttons on this page allowing the CATI
interviewer to play, pause or stop the sound clip, “radio1.wav”, it will not start automatically. Using this syntax:
^StartCatiAudioPlayback("radio1.wav", 1)^ upon displaying this page the sound file would immediately be played.
A CATI interviewer can use the play, pause and stop toolbar buttons to control the playback of the audio file and
whenever the audio file is playing both the interviewer and the respondent will hear it. These buttons are only active
for questions that make use of the sound playback capabilities. Sound file playback will automatically be stopped if the
CATI interviewer submits the current page.
Note: It is the responsibility of the survey author or the person who manages the local dialer to ensure that
the sound file has been placed in the appropriate directory on the dialer(s). This task is not automated in any
way by the Forsta system. If the file cannot be located and played by the dialer the interview will continue as
if the there was no request to play a sound file.
10.1.8.25. IsInOpenendReviewMode
IsInOpenendReviewMode()
- 121 -
Forsta v2022 Scripting Manual Forsta Confidential
This function is only applicable for CATI-enabled projects, being interviewed in the CATI channel.
IsInOpenendReviewMode returns true if the function is executed during CATI openend reviewing, false otherwise.
You may use this function to prevent questions from appearing during openend reviewing either as part of a question
mask or from condition logic. This would typically be used for open text questions that do not require review at the end
of the CATI interview.
Note: If you use this masking, remember to check the "No cleaning on question masking" property (refer to
the separate Survey Designer user guide for more information). If this property is not checked, then the data
will be cleared if the page is empty.
10.1.8.26. AddRespondentToCati
AddRespondentToCati(extendedStatus)
This function is only applicable for CATI-enabled projects, and applies to interviews being conducted in the Web
interviewing mode. It is designed for open surveys where respondent data has not been loaded into the system and
the Web respondent needs to continue the survey in the CATI interviewing channel. When this function is called the
current respondent will be initialized in the CATI system and be available to be interviewed on in the CATI interviewing
channel. If a record already exists for that respondent ID in the CATI interviewing channel the existing respondent will
be updated and have the specified extended status value allocated to it.
The extendedStatus parameter that is supplied is the numeric value of the extended status (between 1 and 120) that
will be assigned to the respondent in the CATI system; call scheduling will be executed on this call using this extended
status value.
The following example demonstrates how this could be used in an open Web survey:
If the answer to the question in “transferToCati” is “Yes” (code 1) then the respondent name and telephone number is
collected and initialized via the script node “initializeCati”. The call is then initialized in the CATI interviewing channel
with an extended status value of 21 (“Transfer to CATI”). The script contains the following code:
SetRespondentValue("respondentname", f("respName"));
SetTelephoneNumber(f("telNumber"));
AddRespondentToCati(21);
Note: You must ensure that a scheduling rule is defined to handle calls with the specified extended status to
ensure that an appropriate CATI call is created.
10.1.8.27. CreateCatiAppointment
CreateCatiAppointment()
This function is available for CATI-enabled projects in Survey Designer. When this function is called, the appointment
dialog will appear on the CATI interviewing console. The interviewer will be able to make an appointment and on
clicking OK the survey will finish with an appointment status. If the interviewer clicks Cancel, they will be allowed to
continue the interview without making an appointment.
Note: This function is only effective if there is an interactive question located after it in the survey. If there are
no interactive questions in the survey after this function is called then the function will be ignored, the
appointment dialog will not appear and the interview will merely continue until it is finished.
- 122 -
Forsta Confidential Forsta v2022 Scripting Manual
10.1.8.28. CreateCustomAppointment
This function can be used when CAWI respondents would like to set up an appointment to be called back via CATI.
The CreateCustomAppointment function can be used in a CATI schedule custom script to create an appointment for
CATI using date and time information captured from survey variables.
The function 'CreateCustomAppointment' will accept parameters for date/time in the respondents time zone.
Example:
function CreateAppointment()
{ var time: DateTime = DateTime.Parse('2021-01-25 13:00');
CreateCustomAppointment(time); }
Refer to the CATI Admin manual for a worked example
Figure 2 The Monitoring and recording options in the CATI Options tab
When the second option for either of these settings is selected, the call monitoring and/or video recording features will
only be permitted after explicit consent has been obtained in the survey. This requires that the survey includes the
corresponding script functions:
EnableLiveMonitoring()
StartScreenRecording()
A simple method of achieving this is to add the functions to a script node inside a condition that is activated by a
"Yes/No" consent question. No parameters are required for the functions.
- 123 -
Forsta v2022 Scripting Manual Forsta Confidential
10.1.8.30. IsCatiGroupMember
IsCatiGroupMember()
The IsCatiGroupMember function can be used to check if the interviewing agent conducting the current interview
belongs to a given group (as specified by the function by referring to it with its applicable group name). The function
returns FALSE if the interviewer is not a member of the specified group.
10.1.8.31. IsCatiIvr
IsCatiIvr()
Use the IsCatiIvr function to determine if the current interview is operating in IVR mode. If this is the case then the
function will return true.
10.1.8.32. IsCatiInbound
IsCatiInbound()
Use the IsCatiInbound function to determine if the current interview was initialized via an inbound call to the call
center. If this is the case then the function will return true.
10.1.8.33.1. GetCatiInterviews
GetCatiInterviews can be used to find other interview records, for example it can be used in an inbound call scenario
to locate a pre-existing interview record when CLI matching is not possible and so a new temporary interview has
been created.
GetCatiInterviews(string[] surveyList, string telephoneNumber, string
respondentName, string filter)
Both telephoneNumber and respondentName parameters work as a “starts with” filter. So if “1234” is specified as a
telephoneNumber, it will search for all numbers starting with “1234”.
These parameters also support wildcards:
- 124 -
Forsta Confidential Forsta v2022 Scripting Manual
10.1.8.33.3. GetCatiLinkedInterviews
GetCatiLinkedInterviews()
This returns a list of “parent” interview records. This is a list of previously started interviews in the current linked
interviews chain (where the SetNextCatiInterview function has been used).
1. With the scheduling script opened in the View mode, go to the Custom Script tab in the lower-right frame.
This tab contains a single text field, which you use to enter your script code.
2. Enter the script code (JavaScript.NET language is used) in the text field. You can also paste the clipboard
contents into this field. Click the Parse button in the lower-right frame's toolbar to check the code is correct.
(see Accessing the Call Object in Custom Scripting on page 125 for more information).
- 125 -
Forsta v2022 Scripting Manual Forsta Confidential
A function exists to initialize a new call inside of the scheduling object when used via a custom scheduling script:
CallShouldBeCreated()
Once initialized Scheduling.NewCall will be initialized and available.
To cancel the creation of the new call, set Scheduling.NewCall to Null.
Object breakdown
BvSurveyEntity object provides access to survey data as follows:
- 126 -
Forsta Confidential Forsta v2022 Scripting Manual
Type Name
int CallID
int SurveySID
int InterviewID
int Phase
int RoleID
int ShiftID
DateTime TimeInShift
DateTime TimeToExpire
int Priority
int Resource
int ApptID
int ResourceType
Guid RuleNumber
Shift functionality is available through the ShiftService object supporting methods when working with shifts:
- 127 -
Forsta v2022 Scripting Manual Forsta Confidential
2. Custom script creates new call with priority which is taken from number variable with 'num_prior' name
function ScriptFunction()
{
CallShouldBeCreated();
Scheduling.NewCall.Priority = f("num_prior").get();
}
3. Custom script creates new call with time to call on next shift
function ScriptFunction()
{
CallShouldBeCreated();
var shift = Scheduling.Shifts.GetMatchingShift( Scheduling.Time,
1/*Timezone*/ );
shift = Scheduling.Shifts.GetNextShift( shift, 1/*Timezone*/ );
Scheduling.NewCall.ShiftID = shift.ShiftTypeID;
Scheduling.NewCall.TimeInShift = shift.StartDate;
}
4. Custom script creates new call and assigns the interviewer with the ID from variable ‘inter’
function ScriptFunction()
{
CallShouldBeCreated();
var name = f("inter").get();
Scheduling.NewCall.Resource = PersonRepository.GetByName( name ).SID;
}
5. Custom script writes the interviewer's SID to variable 'history' (for all interviewers who have conducted an
interview)
function ScriptFunction()
{
var history= f("history").get();
var name : String = "";
if( Scheduling.Interview.LastCallPersonSID != 0 )
{
var person =
PersonRepository.GetByID(Scheduling.Interview.LastCallPersonSID);
if( person != null )
{
if( String.InNullOrEmpty(history))
history = person.name;
else if( !String.Split( history, ',' ).Any( x => x == person.name ) )
history = history + "," + person.name;
else
return;
f("history").setValue(history);
}
}
}
10.1.9.1. CapiAssignRespondent
CapiAssignRespondent(“interviewername”)
- 128 -
Forsta Confidential Forsta v2022 Scripting Manual
This function can be used to allow CAPI assignments to be added to the current respondent, meaning this interview
will then be available for the CAPI interviewer to work on in the CAPI channel.
If the CAPI channel is not enabled for the survey, or if an invalid CAPI interviewer name is provided, the survey will
continue and the survey author will receive an error email.
If the record is already assigned to another interviewer, calling this function will replace the existing assignment with
the new assignment.
Note: This function is intended to be initiated while running in CAWI to facilitate transition of an online survey
to an offline survey in CAPI.
10.1.9.2. CapiUnassignRespondent
CapiUnassignRespondent()
This function can be used to remove an interviewer assignment from this respondent.
If the CAPI channel is not enabled for the survey, the survey will continue and the survey author will receive an error
email.
Note: This function is intended to be initiated while running in CAWI to facilitate transition of an online survey
to an offline survey in CAPI.
10.1.10. Chart
10.1.10.1. ChartTotal
ChartTotal(chartID)
ChartTotal returns the current total number of responses in the question the chart with the id chartID is based on. The
function is typically used in conditions to prevent showing the chart until a minimum number of responses is reached.
10.1.11. Quota
Note: The functions described in this section are not supported by CAPI.
- 129 -
Forsta v2022 Scripting Manual Forsta Confidential
10.1.11.1. qf
The function qf is used to check if a quota is full.
qf(quotaName)
qf will check if the quota quotaName is full with the current respondent's answers on the questions the quota is
based on, and will return true if it is full and false if it is not.
If the respondent qualifies for several quotas within quotaName, qf returns true if one of these is full, and false if
none of them are full. If Optimistic Quota is enabled on quotaName then the In Progress counts are considered by the
qf() function.
Note: The use of redirects, quotas, status-screened or other solutions with the principle purpose of avoiding
the survey "complete" status being reached by a respondent having offered a reasonable amount of
responses, is prohibited and will be regarded as an attempt to avoid transaction fee obligations to Forsta.
Quota Check
If a quota genderQuota is based on a question gender, and the quota is full for males and not full for females,
qf("genderQuota")
will return true if the respondent has answered "Male" on the gender question, and false if the respondent has
answered "Female" on the gender question.
Sometimes you have quotas based on a brand list, where the respondent may qualify for several of the quotas, but
you want to pick only one of the brands the respondent has chosen and ask a set of questions for that brand only. Out
of the brands the respondent has chosen, there should be picked a brand where the quota is not full yet. To check
this, we have to try to set the quota question and use qf to check the quota until we find a brand where the quota is
not full.
Let us say there is a multi question brands, and from this question one of the brands answered should be picked, if
the quota is not full for that brand. We set up a hidden single question chosen_brand that should hold this brand. The
quotas will be set up based on this question in the quota brandsquota.
The script will try to set chosen_brand to a brand chosen in brands, check the quota and continue to next brand if the
quota is full. If the quota is not full, the current brand will be used.
var answers = f("brands").categories(); //codes of all brands selected
for(var i : int = 0;i<answers.length;i++) //iterate through the codes
{
var code = answers[i]; //current code
f("chosen_brand").set(code); //try to preset this code
if(!qf("brandsquota")) //check if quota is not full for this code
{
break; //if quota is not full, keep this brand
}
}
- 130 -
Forsta Confidential Forsta v2022 Scripting Manual
After this script chosen_brand will either be set to a brand where the quota is not full, or if the quota is full for all the
brands chosen_brand will be set to the last one. Typically the interview should terminate if the quotas are full for all
the brands answered, so after the script there should be a normal quota check in a condition, and then an info and a
stop node with quotafull status in the then-branch. The expression in the condition should be like this:
qf("brandsquota")
10.1.11.2. qc and qt
The function qt is used to retrieve the target set for a particular quota, and qc is used to retrieve the current count.
qt(quotaName)
qc(quotaName)
qt and qc both return an integer. They will return target and count for the quota cell in the quota quotaName
corresponding with the current respondent's answers on the questions the quota is based on.
If the respondent qualifies for several quotas within quotaName, qt and qc will return -1.
Note: Quota functions require a database, so will not work in Quick Test / External Quick Test.
var code;
var lowestCode;
/*Loops through all the alternatives in q1 and checks whether the quota
count is lowest with that answer*/
form.set(lowestCode);
Here "q1" is the question id for the question with an answer per web page layout tested (should normally be a hidden
question). "quota1" is the quota id for the quota used in the survey. Now you can create skip logic in the survey based
on q1.
Note: It is important that the quota ‘quota1’ does not have any quota cells set to 'Any' for this example. If that
is the case then the respondent will qualify for several quota cells, and the qc() function will then return -1
which will stop the script working as required.
If the Total rows or columns of the quota have been changed manually in quota Grid View, then an 'Any' row
may be added to the table automatically. The respondent will then always qualify for both one of the answer
choices AND the Any cell, hence resulting in -1 being returned by these functions.
10.1.11.3. GetLeastFilledQuotaCodes
The function GetLeastFilledQuotaCodes is used to retrieve an ordered array of codes for the least filled quota cells for
a specific quota.
- 131 -
Forsta v2022 Scripting Manual Forsta Confidential
Note: In quick test mode, external test mode and through RDG, this function returns an empty array. See
below.
For testing purposes you can create your script so that the GetLeastFilledQuotaCodes() function is only called when
in production mode, and script another way to select quota cells for any of the test modes. For example:
if(IsInProductionMode())
{
f("top_5_cars").set(new Array(GetLeastFilledQuotaCodes('quota1',
5,f("cars_driven").categories())));
}
else
{
SetRandomCategories(5,"top_5_cars"); //test mode so select 5 random
quota cells
}
For a quota based on multi choice question, answers code(s) without the prefix questionName_ are returned. Quota
cells that are already full or that have a target value of 0 are not returned. For a quota based on a single choice
question, [Any] cells are not considered and are not retuned by the function. For a quota based on a multi choice
question all answers should be [Any] except one which should be [Chosen]; only cells with this structure are
considered by the function.
In this example:
There is an interactive multi choice question “cars_driven”, a hidden single choice question “car” and a hidden multi
choice question “top_5_cars” has the same answer list. Of the cars selected in “cars_driven” the quota cell that is
least filled is assigned to the question “car”, and the top five least filled quota cells are assigned to the question
“top_5_cars”. This is achieved using the “assignValues” script node, the contents of this is:
//Find the least filled quota cell and assign it
- 132 -
Forsta Confidential Forsta v2022 Scripting Manual
f("car").set(GetLeastFilledQuotaCodes('quota1',
1,f("cars_driven").categories()).toString());
//Find the top 5 least filled quota cells and assign them
f("top_5_cars").set(new Array(GetLeastFilledQuotaCodes('quota1', 5,
f("cars_driven").categories())));
The loop “l1” is then masked based on the value assigned to the question “car”, meaning that only the chosen car
(least filled quota) will have the loops questions asked.
Note that the ...(new Array()... is required because Forsta returns a standard .NET array type but "Array" in
JScript.NET is different; this then eliminates any possible incompatibility.
Other examples of using this function include:
Note: The GetLeastFilledQuotaCodes() function is calculated every time the function is called, therefore if it is
executed several times in the same interview, the values returned could be different due to either the state of
the quotas changing or due to the random selection of cells that are equally full in percentage terms.
Note: This function does not take into account the Optimistic Quota setting. I.e. in an Optimistic Quota the
returned array is ordered based on the percentage of Counter/Target and does not include the In Progress or
Optimistic Total Limit.
If Optimistic Quota is enabled on a quota that is used with GetLeastFilledQuotaCodes(), then potentially the function
could return quota cell codes where interviews are In Progress and therefore quota cells could overachieve their
targets if the In Progress interviews complete. By using qf() and GetLeastFilledQuotaCodes() it is possible to check if
the least filled cells are already optimistically full. Below is an example script:
var qtaId = "aQuotaId"; //a quota that has Optimistic Quota enabled
(there is no additional advantage in using this script unless Optimistic
Quota is enabled)
var qid = "qtaQuestion"; //the question on which the quota is based
var n = 99; //this should be the number of cells defined in
the quota
var openCells = GetLeastFilledQuotaCodes(qtaId,n);
var leastFilled;
var stop = false;
if(openCells.length>0)
{
var leastFilled = openCells[0];
for(var i=0; !stop && i<openCells.length; i++)
{
var currCell = openCells[i];
f(qid).set(currCell);
if(qf(qtaId))
{
//optimistically, In Progress interviews might fill this cell soon,
discount it
f(qid).set(null);
}
else
{
//this cell is included in Least Fill and also isn't optimistically full,
let's use it and stop the for() loop:
- 133 -
Forsta v2022 Scripting Manual Forsta Confidential
stop = true;
}
}
if(!f(qid).toBoolean())
{
//all quota cells are OPTIMISTICALLY full, maybe redirect the interview
to some quota full handling call block?
}
}
else
{
//all quota cells have achieved targets, redirect the interview to some
quota full handling call block
}
10.1.12.1. SetPanelistCredit
SetPanelistCredit is used for giving panelists points for registering in the panel and responding to surveys.
SetPanelistCredit can be used in Basic Panels, Standard Panels and Professional Panels.
SetPanelistCredit(credit, comment)
SetPanelistCredit(credit, comment, sectionId)
SetPanelistCredit(credit, comment, panelistId)
SetPanelistCredit(credit, comment, panelistId, sectionId)
All of these update a global credit counter in the panel called CreditBalance which can be found inside the
PanelistParticipation folder. The instance of the function that is being used, depends on the number of parameters
and their type.
credit is an integer that represents the number of points that is to be added to the balance. comment is a String that
can be used to include some information about why the points were added. The limit for comment is 256 characters.
If you include just credit and comment as parameters, you set credit points to be added to the credit balance from
the survey the panelist is responding to. These points will be added as soon as interview status is set to "complete",
"screened" or "incomplete" for the respondent. A repeated call to the function in the same survey will overwrite the
previous credit assigned for the survey.
If you would like to assign different sets of points for different parts of a survey, you can also include sectionId.
sectionId is a String with maximum 40 characters that can identify different parts of the survey. You can call the
sections whatever you like as long as you are within the 40 character limit and do not use Unicode characters. The
credits (points) will be active as soon as the respondent's interview status is set. If the panelist does not have any
status (=incomplete), a pending flag will be set and the points will not become active until the status changes to for
example "complete", "screened" or "quotafull".
If you need to update points for a different panelist, you can do this by including the panelistId (integer) of that
panelist. This can for example be done to credit panelist's that refer friends to the panel. You may send the panelistid
(respid in panelist survey) of the panelist that referred into the survey in the URL and retrieve it with Request(see
QueryString on page 228 for more information), and then use SetPanelistCredit to credit his/her points balance.
Note: Panelistid must be a valid number/integer. If panelistid is a String, then the current panelist will be used
irrespective of the panelistid value.
SetPanelistCredit() can over-write an existing row depending on how the function is called. The full function call,
including all arguments is:
SetPanelistCredit(credit, comment, panelistId, sectionId)
- 134 -
Forsta Confidential Forsta v2022 Scripting Manual
Credit and comment are required arguments. If you wish to make more than one set from a “single survey record”,
you will also need to include the sectionId.
Example: Assuming a starting credit value of 5000, run the following script for a specific record in the survey:
SetPanelistCredit(-1000,'redemption')
At this point you will have a balance of 4000. If you change the script to the following and re-launch and re-enter:
SetPanelistCredit(-2000,'redemption')
on viewing the balance you will see 3000, not the expected 2000. If you wish to have each expression counted
“separately”, you must add a sectionId. This will cause separate rows to be written for each. For example:
SetPanelistCredit(-1000, 'redemption','R-20130827170301')
In the example, a sectionID of "R-" is specified and then YYYYMMDDHHMMSS is appended. This is pulled from a
new Date() object. You can alter your code to send in a sectionID that will be different each time a panelist runs over
the script. This ensures that a new row will be written.
Note: If you just want something unique per row, use .getTime() from a new Date() object.
Note: comment is limited to 256 characters and sectionId is limited to 40 characters.
Also note that rows are marked 'pending' until a status (complete, screened, etc ) is set for the record.
10.1.12.3. GetPanelistCreditBalance
GetPanelistCreditBalance()can be used to retrieve the credit balance for a panelist as an integer. You can get
either the total balance or the balance within a specific period. GetPanelistCreditBalance is supported in Basic Panels,
Standard Panels and Professional Panels.
GetPanelistCreditBalance()
returns the current total for a panelist as an integer.
With the Date Time parameters fromDate and toDate you can get the balance for a panelist within a specific period
as an integer (the sum of all the transactions within that period), e.g:
GetPanelistCreditBalance(fromDate, toDate);
- 135 -
Forsta v2022 Scripting Manual Forsta Confidential
function last30()
{
var toDate : DateTime = DateTime.Now;
var fromDate : DateTime = toDate.AddDays(-30);
return GetPanelistCreditBalance(fromDate,toDate);
}
10.1.12.4. GetPanelistCredits
The GetPanelistCredits function can be used to retrieve a subset of a panelist's transactions, as an array of
PanelistCredits objects. GetPanelistCredits is supported in Basic Panels, Standard Panels and
Professional Panels.
GetPanelistCredits(topN);
GetPanelistCredits(fromDate,toDate);
GetPanelistCredits(topN, fromDate, toDate, startPosition,
orderAscending);
GetPanelistCredits(topN) will return an array of PanelistCredits objects (see below), representing the last topN
transactions. topN is an integer.
GetPanelistCredits(fromDate,toDate) will return an array of PanelistCredits objects (see below),
representing transactions performed between fromDate and toDate. fromDate and toDate are both of type
DateTime.
GetPanelistCredits(topN,fromDate,toDate,startPosition,orderAscending) will return an array of
PanelistCredits objects (see below), representing the first topN transactions performed between fromDate and
toDate, if ordered ascending (true for orderAscending) or descending (false for orderAscending). topN is an
integer, fromDate and toDate are both of type DateTime and orderAscending is Boolean.
The PanelistCredits objects in the array returned have the following properties:
pCredit.CreditId
CreditID (integer) is the unique identifier for a transaction.
pCredit.PanelistId
PanelistID (integer) is the responseid of the panelist the credits are assigned to.
pCredit. SecondaryPanelistId
SecondaryPanelistId (integer) is the responseid of another panelist. This field holds a different panelistid if points
have been set from a different panelist’s survey (for example for referrals).
pCredit.PanelistTransactionId
PanelistTransactionId (integer) is the id of the transaction, unique to this panelist.
pCredit.SectionId
SectionId (String) is an identifier a survey designer may assign to the credits, for example if assigning credits to
panelist at various points in the survey.
pCredit.SurveyId
SurveyID (String) is the project number (pXXXXXX) of the project the credits were assigned from.
pCredit.Credit
Credit (integer) is the number of credits (points) assigned to the panelist in this transaction. A negative number
would represent points withdrawn.
pCredit.Comment
Comment (String) is a text assigned to the transaction, for example explaining what the transaction represents.
pCredit.Created
Created (DateTime) is the time the transaction was made (added).
- 136 -
Forsta Confidential Forsta v2022 Scripting Manual
pCredit.Pending
Pending (Boolean) represents whether the transaction is pending (not active) or not. If the transaction is pending, the
flag is set to true, if not, it is set to false.
Retrieving and Listing the last 10 Panelist Credits Transactions inside a Survey
The following functions will list out the date, project number and credits (points) of the last 10 credits transactions
assigned to the current panelist in an HTML table:
function ShowCredits()
{
_var pCredits = GetPanelistCredits(10);
_var txt = "<table>\n"
_txt += "<tr><td>Date</td><td>Project</td><td>Points</td></tr>\n";
_for(var i : int = 0;i<pCredits.length;i++)
_{
__txt+="<tr><td>"+pCredits[i].Created+"</td>";
__txt+="<td>"+pCredits[i].SurveyId+"</td>";
__txt+="<td>"+pCredits[i].Credit+"</td></tr>\n";
_}
_txt += "</table>\n";
_return txt;
}
Retrieving and Listing the last 10 Panelist Credits Transactions inside a Survey,
including custom variables
The following functions will list out the date, project number, credits (points) and the two custom variables listed in the
array fieldNames, of the last 10 credit transactions assigned to the current panelist in an HTML table:
function ShowCreditsWithCustomVariables()
{
var fieldNames = ['customVariable1', 'customVariable2'];
var pCredits = GetPanelistCreditsWithCustomVariables(10, fieldNames);
- 137 -
Forsta v2022 Scripting Manual Forsta Confidential
This setting will allow scripts in the survey to add new panelists to the panel database and retrieve and update data
from the panel database for the current panelist. Very often the registration and profile update surveys will be linked
from the Panel Portal.
10.1.13.1. CreatePanelist
In a registration survey linked to a Panel as described below, the person registering to participate in the panel can be
asked for email (which will be used as the login name and unique identifier), password and other information. The
panelist can be added to the panel database with the CreatePanelist function:
CreatePanelist(fieldNames, fieldValues)
CreatePanelist will return the panelist id (positive integer) if the insert succeed, or a negative integer if the insert of a
new panelist fails, for example because a panelist is already registered with the provided email address (see below).
The parameters are both arrays of Strings: fieldNames are names of the fields in the panel database to insert data
into, and fieldValues are the corresponding values to insert into these fields. fieldNames needs at least to
include “email”, but if the panel database has other user provided unique fields, these fields need to be included as
well.
The codes returned from the insert of a new panelist are listed below. A negative code (less than zero) represents an
error and means that the panelist creation did not succeed.
Code Description
>0 The panelist was created successfully. A new panelist record is added to the database and the panelist
id is returned.
-1 Error on the survey end, for example not being able to connect to the panel database etc.
-2 The unique constraint is violated, i.e. a panelist already exists with the provided values in the unique
fields (email + any user provided unique fields)
- 138 -
Forsta Confidential Forsta v2022 Scripting Manual
10.1.13.2. UpdatePanelVariables
If a survey is linked to a Panel as described above, and the panelists are identified either through panelistid being
included in respondent table (a survey you have sampled to), because the survey is opened within a protected page
(requires login) in the panel portal (profile update), or because you have just inserted this panelist with the
CreatePanelist function (registration survey), you may use the UpdatePanelVariables function to update variables
in the panel database.
UpdatePanelVariables(fieldNames, fieldValues)
The parameters of the UpdatePanelVariables function are both arrays of Strings: fieldNames are names of the
fields in the panel database to update, and fieldValues are the corresponding values to set in these fields.
UpdatePanelVariables will return a negative integer if the update fails:
Code Description
0 Update successful.
-1 Error on the survey end, for example not being able to connect to the panel database etc.
-2 The unique constraint is violated, i.e. another panelist already exists with the provided value(s) you are
trying to set for (one of) the unique field(s) (email + any user provided unique fields).
- 139 -
Forsta v2022 Scripting Manual Forsta Confidential
Here is an example from a survey linked to a Panel as described above, where the questions gender, dateofbirth,
USstate, householdsize, carowner, empstatus, marstatus and email are asked. A hidden open text question
status_desc is used to store the status returned from the update call. The following script can be placed in a script
node to update these variables in the panel database for the current panelist:
var fieldNames : String[] =
["gender","dateofbirth","USstate","householdsize","carowner","empstatus",
"marstatus","email"];
var fieldValues : String[] =
[f('Gender'),f('dateofbirth'),f('USstate'),f('householdsize'),f('carowner
'),f('empstatus'),f('marstatus'),f('email')];
var result = UpdatePanelVariables(fieldNames, fieldValues);
10.1.13.3. GetPanelVariables
If a survey is linked to a Panel as described above, and the panelists are identified either through panelistid being
included in respondent table (a survey you have sampled to) or because the survey is opened within a protected page
(requires login) in the panel portal (profile update), you may use the GetPanelVariables function to update
variables in the panel database.
GetPanelVariables(fieldNames)
Note: If this function is used in a survey, then the survey must be launched as a Limited survey. Failure to do
this will result in an error message being generated for each respondent who attempts but fails to enter the
survey either because they are not uploaded or because they do not enter via a portal.
GetPanelVariables will retrieve values from the fields provided in fieldNames (array of Strings) and return these
values. The data types will be according to the question types (for example date, numeric, open text etc.).
- 140 -
Forsta Confidential Forsta v2022 Scripting Manual
10.1.13.4. UpdateSurveyHistoryPanelVariables
The function UpdateSurveyHistoryPanelVariables replaces UpdateSurveyHistoryVariables, and is used for updating
the survey history of a panelist directly from a script in the panel survey. It requires that the survey from which it is
called is linked to the panel as described previously.
UpdateSurveyHistoryPanelVariables(fieldNames, fieldValues)
fieldNames and fieldValues are both arrays. fieldNames holds the variable names of the survey history variables you
want to update, and fieldValues the corresponding values to assign to them.
- 141 -
Forsta v2022 Scripting Manual Forsta Confidential
IsFromCommunityPortal() returns true if the survey is opened from the Panel Portal and false if not. The
function can be used to determine when to redirect to the Panel Portal Url provided by the
GetCommunityPortalReturnUrl function.
GetCommunityPortalReturnUrl()
GetCommunityPortalUrl() returns a URL that can be used to redirect back to the Panel Portal, with
authentication (so that the panelist does not need to log on again if he/she was already logged in).
10.1.13.7. IsFieldValueTaken
In Professional and Standard Panels it is possible to set panel variables to be unique. That means that each panelist
must have a unique value in this field. The isFieldValueTaken function can be used in panelist recruitment surveys to
check if any previous respondents have selected the same value in a given field.
isFieldValueTaken(fieldName, value)
isFieldValueTaken returns true if there is already a panelist in the sample with the provided value (string) in the
question with question id fieldname (string), false otherwise.
It can be used in the validation code of the question defined in "uniqueid" in a panel survey:
if(isFieldValueTaken("uniqueid", f("uniqueid").get()))
{
SetQuestionErrorMessage(LangIDs.en,"The value in uniqueid is already
taken. Please input a different value.");
f("uniqueid").set("");
RaiseError();
}
The function can also be used in the same way in ordinary projects to check that the value entered in a question with
a given question id is unique. If the function is used in ordinary projects, performance will be improved if the Indexed
property is set on the question being checked. If the function is used to check variables in a panel, again performance
will be improved if the Indexed property is set on the variable being checked.
Note: This function is not supported in RDG, quick-test and external test mode.
When connected to a panel (Professional, Standard or Basic), this function will look in the panel database to see if the
value is taken. When used in a normal survey not connected to a panel, the function will look in the survey database.
Note that if the qid referenced in isFieldValueTaken(qid,value) does not exist in the panel database the function will
always return true.
10.1.13.8. isEmailTaken
The isEmailTaken function is used in panelist recruitment surveys in the same way as isUsernameTaken; to
check if any previous respondents have registered with the same email address.
isEmailTaken(email)
isEmailTaken returns true if there already is a panelist in the sample with the provided email (string), false
otherwise.
- 142 -
Forsta Confidential Forsta v2022 Scripting Manual
The function can also be used in the same way in ordinary projects, to check that the value entered in a question with
question id email is unique. If the function is used in ordinary projects, the indexed property should be set on the email
question to improve performance.
Note: This function is not supported in RDG, quick-test and external test mode.
Note: If you call the function from a survey that is connected to a panel (for example a registration/update
profile survey), then the string argument is compared with the email column in the panel, while if the function
is called from a survey that is not connected to any panel, then the argument is compared to the email
column in the response database of the actual survey.
10.1.13.9. DeleteCurrentResponse
Since the data of registration and profile update surveys are usually posted back to the panel database before the end
of these surveys, it is usually not necessary to keep the data in the survey itself. Therefore a function is provided to
enable deletion of the entire response at the end of the survey after all update scripts have been run:
DeleteCurrentResponse()
DeleteCurrentResponse will remove the entire record with all responses from the survey database.
When DeleteCurrentResponse is used at the end of the survey in a script node, it should be followed immediately by a
redirect script. This is because any attempt to open a survey page (including the end page) after the record has been
deleted will give an error, as the respondent no longer exists (see IsFromCommunityPortal and
GetCommunityPortalReturnUrl on page 141 for more information).
With the "Sample Only" add-on enabled, you can upload a repository of external survey links to the sample job. To
upload the links:
Create a text file (.txt) with 'Link' as the only column header and the external survey links listed, one link per row. On
"Job Information", the interface shown below is available to upload external survey links to the job:
These survey links will then be included in the sample file(s). These can then be uploaded to a Forsta survey, which
must be linked to a Panel on Project Overview:
- 143 -
Forsta v2022 Scripting Manual Forsta Confidential
The following function can be used in this survey to handle redirects and statusing:
RedirectToExternalSurvey(queryString)
RedirectToExternalSurvey will redirect the panelist to the url uploaded to the background variable
"ExternalSurveyLink", with querystring (optional, String) added to the link. querystring can be used if you need
to send in some values with the link. This can be useful if the system running the survey is capable of fetching these
values sent in with the link.
For example, if you have a background variable gender in the sample file, you could send in that value with the
external survey link by using:
RedirectToExternalSurvey("?gender="+f("gender").get())
If you send in several parameters like this, then you must separate them with the ampersand (&) character.
The RedirectToExternalSurvey function will also set a session cookie that will be used when panelists are
redirected back to the survey after finishing the external survey, to identify the panelist and set the correct status on
the panelist for this job.
At the end of the external survey, there should be a redirect back to the survey with the correct status in the survey
link. This status will then be set both on the redirect survey, and back to the panel (in survey history). The statusing
URL is one of the following:
http://<server>/wix/<pid>.aspx?status=complete
http://<server>/wix/<pid>.aspx?status=screened
http://<server>/wix/<pid>.aspx?status=quotafull
http://<server>/wix/<pid>.aspx?status=incomplete
http://<server>/wix/<pid>.aspx (this will default to complete)
<server> is to be replaced with either survey.confirmit.com or survey.euro.confirmit.com if you are a SaaS user, or
your system’s survey domain if you are an On-Premise user. <pid> is to be replaced with the project id of the survey
that is used for the redirect.
When panelists are redirected back, the system will retrieve the necessary information from the cookie to identify the
panelist so that the right status is set, and open the survey after the redirect. The survey will be opened on the node
following the script node with the Redirect script (for example a question, a script node or a stop node). Additional
questions or scripts, for example to set Panelist Credits (points), can be placed after the Redirect script to be executed
when the panelist is redirected back to the redirect survey. The redirect survey will be opened automatically at the
point where the redirect was done when the panelists return from the external survey, due to the details stored in the
cookie.
The cookie is a "session cookie", so is removed when the panelist closes his/her browser.
The function GetExternalSurveyState can be used to keep track of what state the panelist is in, i.e. whether
status has been set or not.
GetExternalSurveyState()
GetExternalSurveyState will return one of the following state codes:
ExternalSurveyState.NONE
ExternalSurveyState.NOT_STARTED
ExternalSurveyState.IN_PROGRESS
ExternalSurveyState.STATUS_SET
The GetExternalSurveyState function is useful if a panelist has disabled cookies in his/her browser. If the
session cookie cannot be found, you will be unable to automatically update the panelist status. To treat this special
case, you can include a condition with the expression
GetExternalSurveyState() == ExternalSurveyState.NONE
- 144 -
Forsta Confidential Forsta v2022 Scripting Manual
followed by a stop node so that these panelists don't cause any errors in scripts you have for example to update panel
variables or points. The text on this stop node could for example notify the panelist that their points status was not
updated automatically and that they will have to wait some days for this to be done, depending on the procedures for
this. It is probably a good idea to flag these incidents by setting a hidden variable as well so that you keep track on
how often it happens.
Note: The statusing survey must have "Encrypt system request parameters" (default) enabled in Survey
Settings/Web for statusing to work.
If you follow the procedure described above, "Interview complete - Sample Only" units will be logged for completes
instead of regular "Interview complete - CAWI ". These units are solely intended to be used by access panel providers
who, as a part of their business, sell sample to other companies, on projects where they do not perform the data
collection themselves. Any other usage of this functionality is prohibited. The following must be in place for the
"Interview complete - Sample only" units to be logged:
10.1.13.11. AddPanelSurveyHistory
This function is used to create a survey history entry for the current panelist, it is used in scenarios where the panelist
is participating in a survey linked to the panel that they are a member of, but have not been directly sampled to.
AddPanelSurveyHistory( panelistId, jobNumber)
The input parameters are strings: panelistId is the panelist’s ID from the linked panel and jobNumber is the job
number in the panel that the survey history entry will be associated with.
The following syntax can be used to update the current panelist in job number 10 in the linked panel. An error will be
reported if the insert fails:
AddPanelSurveyHistory(GetRespondentValue('PanelistId'),"10");
The following criteria must be met for the panelist’s survey history to be updated successfully:
Note: This function is required when a Survey Router is used to route panelists from one survey to another
where the routed-to survey is one that the panelist was not sampled to.
- 145 -
Forsta v2022 Scripting Manual Forsta Confidential
Note: Basic Panels is a Forsta add-on. If you do not have access to this functionality, contact your Forsta
account manager for more information.
10.1.14.1. isUsernameTaken
In Basic Panels, the unique identifier for a panelist is the panelist's username. The IsUsernameTakenfunction is
used in panelist recruitment surveys to check if any previous respondents have selected the same username.
isUsernameTaken(userName)
isUsernameTaken returns true if there is already a panelist in the sample with the provided userName (string) in
the question with question id "username", false otherwise. Note that the question id must be "username".
It is used in the validation code of the username question (mandatory) in a panel survey:
if(isUsernameTaken(f("username").get())){ SetQuestionErrorMessage(LangI
Ds.en,"User name taken. Please choose another user
name."); f("username").set(""); RaiseError();}
The function can also be used in the same way in ordinary projects, to check that the value entered in a question with
question id "username" is unique (note that the question must have the question id "username"). If the function is used
in ordinary projects, the indexed property should be set on the username question to improve performance.
Note: If you call the function from a survey that is connected to a panel (for example a registration/update
profile survey), then the string argument is compared with the username column in the panel, while if the
function is called from a survey that is not connected to any panel, then the argument is compared to the
username column in the response database of the actual survey.
- 146 -
Forsta Confidential Forsta v2022 Scripting Manual
Note: The Date question type gives a date input box and calendar popup, and has built-in validation so that
you do not need to use IsDate or IsDateFmt to validate the date.
Here is a script you can use in the validation code of such a question:
if(!IsDateFmt(f("date1").get(),"YYYY-MM-DD"))
{ RaiseError(); SetQuestionErrorMessage(LangIDs.en,"Invalid date.
Please correct. Use the format YYYY-MM-DD"); }
- 147 -
Forsta v2022 Scripting Manual Forsta Confidential
The grid's answer list will be years, months and dates. It is important that you define codes that are equal to the
number of the years, months (1-12) and dates (1-31):
- 148 -
Forsta Confidential Forsta v2022 Scripting Manual
Here is a script you can use in the validation code of such a question, using the IsDate function with the different
date parts (the grid questions) as arguments:
if(!IsDate(f("day")["1"].get(),f("month")["1"].get(),f("year")["1"].get()
))
{
RaiseError();
SetQuestionErrorMessage(LangIDs.en,"Invalid date. Please correct.");
}
10.1.15.3. IsEmail
IsEmail( argument )
- 149 -
Forsta v2022 Scripting Manual Forsta Confidential
IsEmail checks whether the argument has the format of a valid email address. It returns true if it has, false
otherwise.
Note: the function does not attempt any name look-ups or address verification, it just checks that the format
is valid (i.e. includes an @ character etc.).
Note: In Survey Designer, users can enable the ‘Email’ property on a Text question. This removes the need
for validation script to check that the answer adheres to email format.
10.1.15.4. IsNet
IsNet(quadIP,quadNet,quadMask)
Determines whether an IP address belongs to an Internet network.
Argument Description
The IP address, in quad form (X.X.X.X.).
quadIP
If no mask is provided then the number of bits that constitute the network part of the address is determined from the
address class type. In this case the function returns true if the IP address' network number is identical to the supplied
network number and it has a non-zero local address. Otherwise it returns false.
If a mask is provided then the function returns true if the IP address' network and subnet parts are identical to the
one supplied and the host number part is non-zero. Otherwise it returns false.
You can use the RequestIP function to get the respondent's IP address (see RequestIP on page 95 for more
information).
10.1.16.1. SendMail
SendMail(from,to,subject,body,cc,bcc,mailformat,bodyformat,codepage)
- 150 -
Forsta Confidential Forsta v2022 Scripting Manual
SendMail can be used to send an email from inside a survey. For information on sending of multipart emails (see
SendMailMultipart on page 153 for more information).
Arguments:
Argument Description
bodyformat* (int)
0 – HTML, 1 – Plain text
codepage* (int)
The codepage the mail is to be sent with. 1252 is Western European, 65001 is
Unicode (UTF-8).
*) optional
The last 5 arguments are optional, but if you include any of them, you have to include all arguments that precede
them. For example, if you do not want a carbon copy (cc), just use an empty string ("") for that argument (see
APPENDIX D: Codepage on page 283 for more information).
//send mail:
SendMail("[email protected]",f("email"),"Thank
you!",body,"","[email protected]");
- 151 -
Forsta v2022 Scripting Manual Forsta Confidential
The email will be sent to the respondent, with a blind copy sent to "[email protected]". The respondent will not know
that this copy has been sent as the address is in the bcc field. You must include an empty string ("") for the cc
argument if you do not want to cc anybody but do want to bcc as in this example. If you need more than one email
address in either to, cc or bcc, separate the addresses with semi colons (;) inside the string, e.g.
"[email protected];[email protected]".
The first condition checks if there is an answer to the email question. The email question is required, so if it has no
answer the respondent should get the first part of the survey.
Then name and email questions follow. In the email question, use the following validation code:
if(!IsEmail(f(CurrentForm()))))
{
RaiseError();
SetQuestionErrorMessage(LangIDs.en,"Please provide a valid email
address.");
}
After the email question there is a script node, which does the emailing (change "survey.confirmit.com" if you are not
using Confirmit's ASP):
var body : String = "Thank you for registering.\r\n\r\n";
body += "Here is the url to your follow up survey:\r\n";
body += GetRespondentUrl()+"\n";
SendMail("[email protected]",f("email"),"Follow up",body);
Then there is a stop node to end the first part of the interview. When the respondent re-opens the interview with the
url, he/she is brought into the same interview with the data from the first part. So since there now is an answer to the
email question, the first part will be skipped and the respondent will be brought to the info node (i4).
However, by default, when a condition in Forsta evaluates to false, the interview engine removes all answers to
questions in the THEN-branch. This ensures that you get consistent data in your surveys and do not have to do data
cleaning. But here, this would mean that the answers to name and email would be deleted, and that is not what we
want – we are going to use name in part 2 of the interview.
Fortunately there is a property on conditions that can be used in situations like these: "Do not perform delete". When
this property is checked, the interview engine will never remove answers in any of the branches (THEN/ELSE).
- 152 -
Forsta Confidential Forsta v2022 Scripting Manual
To pipe in the name in the first info node (i4), use the code below:
^f("name")^
10.1.16.2. SendMailMultipart
SendMailMultipart(from,to,subject,bodyText,bodyHtml,cc,bcc,codepage)
SendMailMultipart can be used to send a multipart email from inside a survey. A multipart email is an email
where the body text can be defined both as plain text and as HTML. The recipient’s mail client will determine which
version is to be displayed to the recipient.
Arguments:
Argument Description
From
Message sender (string)
to
Recipient's address (string)
Subject
Message subject line (string)
BodyText
Message body, plain text (string)
BodyHtml
Message body, HTML (string)
cc*
Carbon Copy (string)
bcc*
Blind Carbon Copy (string)
Codepage*
(int) The codepage the mail is to be sent with. 1252 is Western European, 65001 is Unicode (UTF-8)
(default value).
*) optional
The last 3 arguments are optional, but if you include any of them, you have to include all arguments that precede
them. For example, if you do not want a carbon copy (cc), just use an empty string ("") for that argument (see
APPENDIX D: Codepage on page 283 for more information).
- 153 -
Forsta v2022 Scripting Manual Forsta Confidential
10.1.16.3. SendPdfMail
The SendPdfMail function allows the generation and emailing of a PDF file from a survey with for example a
summary of the respondent's answers. Typically the file is sent to the respondent, but it could also be sent to
someone who is to review the respondent’s answers. Note that you can also send PDF mail with copies (see
SendPdfMailWithCopy on page 155 for more information).
Note: PDFs are only sent when the device is synched with the server.
Argument Description
html
A string with the html that the PDF file should be created from.
emailSender
The sender of the message.
emailReceiver
The recipient's address.
emailBody
The message body text (optional).
emailSubject
The message subject (optional).
outputFileName
The filename of the pdf file (optional). Note that the filename can only contain alphanumeric
characters. Do not specify the extension of the file.
pdfPageSize The paper size for which the PDF is formatted (optional). Valid options are A3, A4, A5, B4, B5,
Legal, Letter and Tabloid.
pdfOrientation The orientation of the page (optional). Valid options are Landscape or Portrait.
companyId The company id (required if pdfPageSize and/or pdfOrientation are included in the function). Each
company has one id. Note that normal users do not have access to this information; you must
contact Forsta support to retrieve it.
useNewPdfEngin (Required if PaperSize and/or Orientation are included in the function) This is a Boolean value
e which can be either true or false.
As the content of the PDF file is a string containing HTML, there is considerable flexibility concerning the layout and
content of such a respondent-specific report.
If no subject is provided, the subject of the email will be “Respondent Report”. If no filename is provided, the name of
the pdf file will be “respondentreport”.
- 154 -
Forsta Confidential Forsta v2022 Scripting Manual
The call to the function initiates a task that runs on the batch servers to generate and send a zipped PDF file. This
means that, depending on the queue of tasks on the batch server, there may be a delay in producing and sending the
file. If the PDF report is to be sent to the respondent, it is recommended that the respondent is informed of this
possible delay. The function will not run in RDG mode.
For SaaS customers there is a charge for each of these reports, just as for PDF exports from Reportal.
The PDF-software does not parse anchor tags; it only adds the link text. So to have clickable links in the PDF file that
is generated with SendPdfMail, you must include the URL itself.
http://www.confirmit.com
NOT:
<a href=” HYPERLINK "http://www.confirmit.com/”%3eLink" http://www.confirmit.com/”>Link text</a>
If you want blue text and underline, you can define this in a <span> tag:
<span style="text-decoration: underline; color: blue">HYPERLINK "http://www.confirmit.com%3c/span"
http://www.confirmit.com</span>
SendPdfMail(html,"[email protected]",f("email").get(),"Here are
your responses to the survey.","Your responses","responses");
Note: Non-ASCII characters are not accepted by the PDF creator. If non-ASCII characters must be used, write
valid HTML for the required character and include a metatag such as the following: <meta http-
equiv="content-type" content="text/html;charset=utf-8" />
10.1.16.4. SendPdfMailWithCopy
The SendPdfMailWithCopy function is an extension of the SendPdfMail function, giving you the possibility to
copy the mail to others. The function allows the generation and emailing of a PDF file from a survey with for example
a summary of the respondent's answers.
Note: PDFs are only sent when the device is synched with the server.
Argument Description
html A string with the html that the PDF file should be created from.
- 155 -
Forsta v2022 Scripting Manual Forsta Confidential
Note that if this function is used, both cc and bcc must be used.
For further details, see SendPdfMail (see SendPdfMail on page 154 for more information).
10.1.16.5. Redirect
Redirect(url,{noexit})
Redirect can be used to redirect the respondents to a different site (url).
Important
If a redirect is included at the end of the survey, it is important that the interview status is also set using the
SetStatus function (see GetStatus and SetStatus on page 87 for more information).
Note: The use of redirects, quotas, status-screened or other solutions with the principle purpose of avoiding
the survey "complete" status being reached by a respondent having offered a reasonable amount of
responses, is prohibited and will be regarded as an attempt to avoid transaction fee obligations to Forsta.
noexit is a Boolean. It is optional, and is used when you want the respondents to be able to reenter the survey, for
example if you redirect out of the survey to another url, and then at some point the respondents are redirected back
to the survey again (with r (respid) and s (sid)). This is especially important if the survey is set up without "Allow user
to modify answers after the interview is complete". With noexit as true, the respondent will be allowed to reenter
the survey. With noexit as false (default), the respondent will not be allowed reentry to the survey.
- 156 -
Forsta Confidential Forsta v2022 Scripting Manual
Note: The use of scripted Redirect() to jump into or out of questions that are in Call Blocks will cause
problems and should not be attempted. A key attribute of Call Blocks is that they can be entered from
multiple points in a survey, so the survey engine will not have a specific “entry-point” that has been used to
enter that call block. Therefore when the Call Block finishes it does not know where in the main body of the
survey to return to, and the survey will simply error. Refer to the separate Survey Designer user guide for
further details on Blocks.
Redirect between surveys, or between the survey and an external application with encrypted links:
You can use Redirect if you need to send the respondent to a different survey or another application. If you need to
send the respondent back into the survey again, then you can add the respondents sid value as a parameter to the
link, and use this to send the respondent back into its unique survey link.
Example:
In this example we will send the respondent from survey A into survey B, then when they complete survey B they are
sent back into survey A directly to question q4.
Survey A includes the script “Redirect to survey B”. This will retrieve sid from the respondent link, and add this as a
parameter to the target link:
//Get the respondent unique survey link for question q4:
var UniqueLink = GetRespondentUrl("q4");
- 157 -
Forsta v2022 Scripting Manual Forsta Confidential
Note: To use parameter __qid and the __gotoCallBlock option, the “Disable unencrypted QID request
parameter” must be unselected in the Overview page > More Survey Settings > Options section (Survey
settings > General Options tab in Professional Authoring).
This setting will allow scripts in the survey to find project IDs to route the respondent/panelist to or perform the routing
itself.
- 158 -
Forsta Confidential Forsta v2022 Scripting Manual
10.1.17.1. GetAvailableSurvey
GetAvailableSurvey is used to get a Project ID that the respondent/panelist could be routed to based upon supplied
selection criteria.
GetAvailableSurvey(fieldnames{, projectList, mode})
The list of question IDs supplied in fieldNames (array of Strings). Up to 5 questions IDs can be supplied (this value is
configurable for On-Premise license holders) that you want to be checked by the Survey Router selection algorithm.
The list of optional project ID to be included/excluded from the selection criteria supplied in projectList (array of
Strings). Mode (Boolean) optional unless a projectList is supplied, determines whether the projectList is an inclusion
or an exclusion list, where true demotes an inclusion list and false denotes an exclusion list.
In the following example both "gender" and "age" questions are considered in the survey selection but both project IDs
"p1234567" and "p7654321" will be excluded from the selectable surveys.
var fieldNames : String[] = ["gender", "age"]
var projectList : String[] = ["p1234567", "p7654321"]
f("targetSurvey").set(GetAvailableSurvey(fieldNames, projectList, 0));
In this example the "gender" question is to be checked. If for example the respondent has answered the "gender"
question in the original survey by stating he is "male", then the survey routing algorithm will check the remaining
surveys in the group and ignore any surveys where the quota for males is already full. As in this case "gender" is the
only selection criteria required, the routing algorithm would now select the survey with the highest priority and open
that survey for the respondent.
Availability of the respondent's quota profile does not consider Optimistically populated (currently active) respondents;
only those that have completed the survey and have caused the quota cell to be incremented.
In the event several projects satisfy the selection criteria and they all have the same priority, a project will be selected
from the group at random.
In the event that no projects satisfy the selection criteria, no project IDs will be returned. When a potential project is
found, the system will verify that the respondent has not already participated in that specific survey (username in the
respondent table is used as the key); if they have then the survey will not be considered as available for selection and
the system will attempt to find another survey. After attempting to find another survey three times (this value is
configurable for On-Premise license holders) due to the fact that the respondent has already participated, the system
will stop trying to find a survey and will return nothing (as if no surveys are available for selection).
An exact match is required for all the criteria listed in the array. So in this case if a survey in the group does not have a
"gender" question, then that survey will not be considered for selection by the algorithm.
10.1.17.2. RedirectToRouterSurvey
RedirectToRouterSurvey is used to seamlessly route the respondent from one survey to another inside of the Survey
Router they are registered with.
RedirectToRouterSurvey(projectId, username, language{, fieldnames})
- 159 -
Forsta v2022 Scripting Manual Forsta Confidential
The survey ID that the respondent is to be routed to is supplied in the projectId (string), the unique identifier for the
respondent is supplied in the username (string), and the optional list of question IDs that are to be passed to the
routed-to survey is supplied in fieldNames (array of Strings). You can explicitly specify the language that the routed-to
survey is to use by supplying the optional language value. This is the numeric identifier for the “l” value. If no language
value is supplied, the survey default language will be used.
In the following example the respondent will be routed to the project ID stored in the question "targetSurvey" using the
unique identifier supplied in the question "uniqueID" and passing the values to questions "age", "gender" and "region".
var fieldNames : String[] = ["age", "gender", "region"]
RedirectToRouterSurvey(f("targetSurvey"), f("uniqueID"), fieldnames);
Open text, single choice and numeric questions can be passed to the target survey, other question types are not
supported. The questions that are passed can be normal, background or hidden, but no validation is performed on the
data until the question is executed in the target survey. If the question passed does not exist in the target survey no
error will be reported.
In this example, if the quota of the current project is filled then the respondent will automatically be routed to a new
project within their Survey Router group. Both age and gender questions will be passed to the target survey.
Note: Survey router redirection will only occur if the Survey Setting > Web Options > Survey type is set to
“Limited survey with external respondent creation” in the target survey.
Typically, you will not want to ask the same questions in the target survey as you have already asked in the initial
survey. To prevent this, a question mask can be applied to the questions that are passed to the target survey. In this
case you may check if the question has already been answered, and if so, do not display the question again:
Note: If you use this masking, remember to check the "No cleaning on question masking" property (refer to
the separate Survey Designer user guide for more information). If this property is not checked, then the data
will be cleared if the page is empty.
10.1.17.3. GetRouterName
GetRouterName()
The GetRouterName() function can be used to return the name of the router that the survey is assigned to. If the
survey is not assigned to a router, this function will return an empty string.
- 160 -
Forsta Confidential Forsta v2022 Scripting Manual
10.1.18.1. CintFulfillmentRespondentsTransition
The CintFulfillmentRespondentsTransition scripting function has the following signature:
CintFulfillmentRespondentsTransition(respondentId: String, status:
String)
Below are examples of how you might use the function to pass one of the three transition status values. Note that all
three are displayed together here; you would only ever use one at a time.
Note: This function requires that an administrator with the Company admin permission adds the Cint API key
to the Company Details page > Security tab. See the Forsta Administrator Manual for further details.
Code examples:
//Complete
SetStatus('complete')
SetInterviewEnd()
CintFulfillmentRespondentsTransition('04fe9a97-a579-43c5-bb1a-
58ed29bf0a6a', 'Complete')
//Screened
SetStatus('screened')
SetInterviewEnd()
CintFulfillmentRespondentsTransition('04fe9a97-a579-43c5-bb1a-
58ed29bf0a6a', 'Screenout')
//QuotaFull
SetStatus('quotafull')
SetInterviewEnd()
CintFulfillmentRespondentsTransition('04fe9a97-a579-43c5-bb1a-
58ed29bf0a6a', 'QuotaFull')
//QualityTerminate
SetStatus('screened')
SetInterviewEnd()
CintFulfillmentRespondentsTransition('04fe9a97-a579-43c5-bb1a-
58ed29bf0a6a', 'QualityTerminate')
The interview would be completed with the specified status and the respondent with the specified respondent GUID
will have the specified status passed over to Cint. Note that in these examples a GUID is hard-coded, however it could
reference a variable within the survey.
• Whenever there are pieces of code that it is likely that you will reuse several times in the questionnaire.
• When you need to refer to values (often computed expressions) that are not stored in survey variables.
• To group statements that perform a well-defined task, to make the code easier to read, and to make your code
more modularized.
Functions can be called from anywhere within the questionnaire.
Type annotation in a function specifies a required type for function arguments, a required type for returned data, or a
required type for both. If you do not type annotate the parameters of a function, the parameters will be of type Object.
Likewise, if the return type for a function is not specified, the compiler will infer the appropriate return type.
- 161 -
Forsta v2022 Scripting Manual Forsta Confidential
Using type annotation for function parameters helps ensure that a function will only accept data that it can process.
Declaring a return type explicitly for a function improves code readability since the type of data that the function will
return is immediately clear.
Note: When calling a function, ensure that you always include the parentheses and any required arguments.
Calling a function without parentheses causes the text of the function to be returned instead of the results of
the function.
- 162 -
Forsta Confidential Forsta v2022 Scripting Manual
Note: The script node defining this function must be placed before the question in which it is called in the
questionnaire tree.
- 163 -
Forsta v2022 Scripting Manual Forsta Confidential
11. Objects
JScript .NET is an object-oriented language. We will not elaborate on the object-oriented features in this manual.
We will just describe the JScript and Forstaobjects that are relevant for survey programmers, and advice the reader to
consult a JScript .NET reference for more in-depth knowledge.
All script code in Forsta is wrapped as functions inside a class. This means that you can not define your own classes
in Forsta scripts.
JScript objects are collections of properties and methods. A method is a function that is a member of an object. A
property is a value or set of values that is a member of an object.
11.1. Properties
Properties are used to access the data values contained in an object.
An object's properties are accessed by combining the object's name and its property name:
objectName.propertyName
We have already seen an example of a property on the Array object, a property called length for the size of the
array (for example, the weekday array from previous examples):
weekday.length
11.2. Methods
Methods are functions that are used to perform operations on an object.
You access a method of an object by combining the object's name and the name of a method:
objectName.methodName(arguments)
Just like in functions, arguments in method calls are optional.
We have already used the basic variable objects of Forsta returned from the f function. We have seen some methods
that can be applied on these objects to retrieve information about the questions in a Forsta survey. For example will
f(qID).label()
return the title of the question with ID qID, and
f(qID).get()
the code or answer stored in the database for that question.
We have also seen a method that can be used to set the answer of a question:
f(qID).set(code)
- 164 -
Forsta Confidential Forsta v2022 Scripting Manual
12.3. Compounds
The f function returns in fact different objects for different question types. These objects have some properties and
methods in common, but some are specific to questions of a specific type.
Grid, multi, open text list, numeric list and ranking questions are questions with one or more variables that are defined
in the same form. They are called compounds. They can be accessed using the f function in the normal manner, but
the object returned is more complex than objects returned from other question types. You can refer directly to each of
their elements using syntax that is similar to that of an array:
x[code]
x represents a variable holding an instance of an object returned from calling the f function on a compound. code is
a string representing the code from the answer list of the compound. An example is referring to the element with code
"1" in a multi question with question ID q2:
f("q2")["1"]
- 165 -
Forsta v2022 Scripting Manual Forsta Confidential
In our previous solution for validation of this question (see The while Statement on page 62 for more information) we
looped through the weekdays. For each day, we called the f function for three questions q2, q3 and q4:
sum = Sum(f("q2")[code],f("q3")[code],f("q4")[code]);
Now, instead we can define three variables sleep, work and leisure to hold the form objects:
var sleep = f("q2");
var work = f("q3");
var leisure = f("q4");
var codes = sleep.domainValues(); // array with all codes
var i : int = 0;
var correctSum : Boolean = true;
while(i<codes.length && correctSum) //iterate through codes (rows)
{
var code = codes[i]; //current code
//calculate sum:
var sum : int = Sum(sleep[code],work[code],leisure[code]);
if(sum != 24)
{
correctSum = false;
}
i++;
}
if(!correctSum)
{
RaiseError();
SetQuestionErrorMessage(LangIDs.en,"Please make sure that the total
number of hours for each day equals 24. Currently the sum for
"+sleep[code].label()+" is "+sum+".");
}
- 166 -
Forsta Confidential Forsta v2022 Scripting Manual
The way the script was initially set up you could have as much as 21 calls (3*7=21) on the f function inside the loop.
We have now reduced this to 3 function calls.
12.4. Properties
The form objects can have the following properties, depending on the type of the question (x represents a form object
returned from the f function):
x.CODED
CODED is true if the question referenced is a coded variable. If not, CODED is undefined. Coded variables are
single questions and loops, and answer list items of a grid or a multi question.
x.OPEN
OPEN is true if the question referenced is an open variable. If not, OPEN is undefined. Open variables are open text
questions, other-specify elements of answer lists and answer list elements of an open text list, numeric list or ranking
question.
x.DICHOTOMY
DICHOTOMY is true if the question referenced is a dichotomy. If not, DICHOTOMY is undefined. The elements of a
multi question (referenced with f(qID)[code]) are dichotomies.
x.COMPOUND
COMPOUND is true if the question referenced is a compound. If not, COMPOUND is undefined. Multi, open text list,
numeric list, ranking and grid questions are compounds.
x.NUMERIC
NUMERIC is true if the question referenced is numeric. If not, NUMERIC is undefined.
x.EXTERNAL
EXTERNAL is true if the question referenced gets its answerlist from Database Designer (either as a lookup table or a
hierarchy).
x.DATE
DATE is true if the question referenced is a date question. If not, DATE is undefined.
x.BOOL
BOOL is true if the question referenced is Boolean (has the Boolean property set). If not, BOOL is undefined.
x.GEO
GEO is true if the question referenced is a Geolocation question. If not, GEO is undefined.
Note: The Boolean property and Date question type are only available when using the Optimized database
format.
These properties are extremely powerful, because by using them it is possible to write generic scripts that will work no
matter what the question type is.
Using a combination of COMPOUND with DICHOTOMY and OPEN enables the user to differentiate between a grid
and a multi and a numeric list, open text list or ranking question since the elements of a multi are a DICHOTOMY, but
DICHOTOMY would be undefined for a grid, numeric list, open text list or ranking, and elements of numeric list, open
text list or ranking are OPEN, but OPEN is undefined for grid and multi.
- 167 -
Forsta v2022 Scripting Manual Forsta Confidential
- 168 -
Forsta Confidential Forsta v2022 Scripting Manual
set X X X X X X X
X
label X X X X X X X X
text X X X X X X X X
instruction X X X X X X X
- 169 -
Forsta v2022 Scripting Manual Forsta Confidential
value X X X X
valueLabel X X
domainValues X X X
domainLabels X X X
categories X
categoryLabels X
values X
getType X X X X X X X X
any X X
all X
none X X
between X
inc X X
size X X
union X X
isect X X
diff X X
members X X
isNearBy X
latitude X
longitude X
- 170 -
Forsta Confidential Forsta v2022 Scripting Manual
13.1. Constructor
An instance of the Set object can be created like this:
s = new Set();
You will also get instances of the Set object returned from the functions a, set, nset, nnset, and Filter.
Note: There is a limitation with this function when qid uses a table lookup for its answerlist. In this case, it
should not be called from the code mask of qid. The workaround is to add an additional hidden single
question which points to the same table lookup, and use that with the a() call instead. So if qid1 uses table
lookup answerlist and needs to call a(qid1) in its code mask, instead it should use a(qid2) where qid2 is a
hidden single question that uses the same table lookup answerlist.
13.2.3. Iset
lset(params)
lset can be used to construct a set. The input to the function can either be an object such as an Array, or a list of
parameters from which the function will create a set.
- 171 -
Forsta v2022 Scripting Manual Forsta Confidential
lset(new Array(1,2,8))
returns a set consisting of the codes 1, 2 and 8.
13.3.1. inc
s1.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")
- 172 -
Forsta Confidential Forsta v2022 Scripting Manual
13.3.2. size
s1.size()
size returns the number of elements in the set s1.
s1.union(s2)
s1.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 s1 and s2.
- 173 -
Forsta v2022 Scripting Manual Forsta Confidential
s1.isect(s2)
s1.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.
- 174 -
Forsta Confidential Forsta v2022 Scripting Manual
s1.diff(s2)
s2.diff(s1)
- 175 -
Forsta v2022 Scripting Manual Forsta Confidential
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.
s1.isect(s2).union(s3)
To force a sub-expression to be evaluated before other expressions, you can insert entire expressions inside the
parentheses of the set methods. In the expression
s1.isect(s2.union(s3))
the sub-expression s2.union(s3) will be evaluated first, and then the intersection between the result of this sub-
expression and the set s1 is computed. The result is a set consisting of all codes both in s1and in either of s2 or s3:
- 176 -
Forsta Confidential Forsta v2022 Scripting Manual
s1.isect(s2.union(s3))
Exercise 6:
You have three sets: s1, s2 and s3. s1 consists of the codes 1,2,5,7,10,11, s2 consists of the codes
3,4,5,8,11,13 and s3 consists of the codes 2,4,5,6,9,10,12, as indicated in the illustration above.
- 177 -
Forsta v2022 Scripting Manual Forsta Confidential
What elements will the sets returned from the following expressions contain?
1. s1.union(s3.diff(s2))
2. s1.union(s3).diff(s2)
3. s1.isect(s2.diff(s3))
4. s1.isect(s2).union(s2.isect(s3)).union(s3.isect(s1))
The answers are given in APPENDIX A Answers to Exercises.
13.3.5. members
s1.members()
members is used to convert a set to an array.
However this setting does not apply to 3D grids since Forsta 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_other
For 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.
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:
- 178 -
Forsta Confidential Forsta v2022 Scripting Manual
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()>0
Then, if the question is ‘empty’, it will be skipped.
- 179 -
Forsta v2022 Scripting Manual Forsta Confidential
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.
- 180 -
Forsta Confidential Forsta v2022 Scripting Manual
14.1.1. Constructors
You can create a new instance of the Date object in three ways:
dateObj = new Date();
dateObj = new Date(dateVal);
dateObj = new Date(year, month, date{, hours{, minutes{,
seconds{,ms}}}});
If you just use the constructor Date(), the instance of the Date object will be set to current date and time.
If you use Date(dateVal) and dateVal is an integer, dateVal represents the number of milliseconds since
midnight January 1, 1970 Universal Coordinated Time. Negative numbers indicate dates prior to 1970. If dateVal is
a string, dateVal is parsed according to the rules in the parse method (see parse on page 182 for more
information)).
Here are two ways of getting an instance of the Date Object that is set to midnight 2000 (UTC):
d = new Date(946684800000);
d = new Date("Sat, 1 Jan 2000 00:00:00 UTC");
When you use Date(year,month,date{,hours{,minutes{,seconds{,ms}}}}), the first three arguments are
required. year has to be the full year, for example 1984 (and not just 84). month is an integer between 0 and 11
(This means that January is 0, December is 11. This is similar to how we have seen that arrays are indexed, where 0
is the first element). date is an integer between 1 and 31.
The next arguments are optional (that's what the curly brackets indicate), but when one of them is included, all
preceding arguments must be supplied. This means that if you specify seconds, it has to be preceded by hours and
minutes. hour is an integer from 0 to 23 (midnight to 11pm). minutes and seconds are integers from 0 to 59 and
milliseconds is an integer from 0 to 999. Here is an example:
d = new Date(2000,0,1,0,0,0,0);
This may or may not be equal to the two examples above using the other constructors. It depends on the server
settings on the Forsta server. The two examples above both use UTC. With this last constructor, the time zone cannot
be specified. The time zone of the Forsta server will be used.
If an argument is greater than its range or is a negative number, other stored values are modified accordingly. So 150
seconds will be redefined as 2 minutes and 30 seconds. The 2 minutes will be added to the minutes value. If this
exceeds 60 minutes, hours will be modified and so on.
- 181 -
Forsta v2022 Scripting Manual Forsta Confidential
• Short dates can use either a "/" or "-" date separator, but must follow the month/day/year format, for example
"7/20/96".
• Long dates of the form "July 10 1995" can be given with the year, month, and day in any order, and the year in
2-digit or 4-digit form. If you use the 2-digit form, the year must be greater than or equal to 70.
• Any text inside parentheses is treated as a comment. These parentheses may be nested.
• Both commas and spaces are treated as delimiters. Multiple delimiters are permitted.
• Month and day names must have two or more characters. Two character names that are not unique are
resolved as the last match. For example, "Ju" is resolved as July, not June.
• The stated day of the week is ignored if it is incorrect given the remainder of the supplied date. For example,
"Tuesday November 9 1996" is accepted and parsed even though that date actually falls on a Friday. The
resulting Date object contains "Friday November 9 1996".
• JScript .NET handles all standard time zones, as well as Universal Coordinated Time (UTC) and Greenwich
Mean Time (GMT).
• Hours, minutes, and seconds are separated by colons, although all need not be specified. "10:", "10:11", and
"10:11:12" are all valid.
• If the 24-hour clock is used, it is an error to specify "PM" for times later than 12 noon. For example, "23:15 PM"
is an error.
• A string containing an invalid date is an error. For example, a string containing two years or two months is an
error.
14.1.2.1.2. UTC
UTC returns the number of milliseconds between midnight, January 1, 1970 Universal Coordinated Time (UTC) (or
GMT) and the supplied date.
Date.UTC(year, month, day{, hours{, minutes{, seconds{,ms}}}})
The arguments are equal to those of the Date(year,month,day{,hours{,minutes{,seconds{,ms}}}})
constructor (see Constructors on page 181 for more information).
If the value of an argument is greater than its range, or is a negative number, other stored values are modified
accordingly. For example, if you specify 150 seconds, JScript .NET redefines that number as two minutes and 30
seconds.
- 182 -
Forsta Confidential Forsta v2022 Scripting Manual
The difference between the UTC method and the corresponding Date object constructor is that the UTC method
assumes UTC, and the Date object constructor assumes local time. (Local time when doing server side scripting will
be the time zone of the Forsta servers, not the time zone of the client (the PC of the respondent)).
The UTC method is a static method. Therefore, a Date object does not have to be created before it can be used.
Date.UTC(2000,0,1,0,0,0,0)
For the methods that set date parts, the other parts of the date are modified accordingly if the value of an argument is
greater than its range or is a negative number. So, if you for example use the setMinutes method with 62 as
argument, minutes will be set to 2 and hours will be increased with 1. If this makes hours exceed its limit, date is
changed to the next day, and so on. This gives a very efficient way of working with dates in scripts.
For all methods with numMonth as argument, remember that JScript .NET months use the numbers 0 to 11. 0 is
January and 11 is December.
- 183 -
Forsta v2022 Scripting Manual Forsta Confidential
numMonth and numDate are both optional. If numDate is supplied, numMonth must also be supplied. numMonth is a
numeric value equal to the month (0-11). numDate is a numeric value equal to the date (1-31).
If you do not specify the optional arguments, the value will be retrieved from the corresponding get method. For
example, if numMonth is not specified, JScript .NET uses the value returned from the getMonth or getUTCMonth
method.
If the value of an argument is greater than its range or is a negative number, other stored values are modified
accordingly.
There are two methods called getYear and setYear. They are obsolete and kept for backwards compability only. It
is not recommended to use them, because of Y2K problems. Use the FullYear methods instead.
0
Sunday
1
Monday
2
Tuesday
3
Wednesday
4
Thursday
5
Friday
- 184 -
Forsta Confidential Forsta v2022 Scripting Manual
6
Saturday
- 185 -
Forsta v2022 Scripting Manual Forsta Confidential
The rest of the arguments are optional. If they are not included, the results from using the corresponding get functions
are used. For example, if numSec is not provided, the result from getSeconds or getUTCSeconds is used. All the
preceding arguments must be included if one of the optional arguments is included. If numMilli is used, numSec
must also be included in the method call.
numSec is a numeric value equal to the seconds value and numMilli is a numeric value equal to the milliseconds
value.
If the value of an argument is greater than its range or is a negative number, other stored values are modified
accordingly. For example, if the stored date is "Jan 1, 2000 00:00:00", and setMinutes(62) is called, the date is
changed to "Jan 1, 2000 01:02:00." Negative numbers have a similar behavior.
- 186 -
Forsta Confidential Forsta v2022 Scripting Manual
14.1.2.2.10. getTimezoneOffset
dateObj.getTimezoneOffset()
Returns the difference in minutes between the time on the host computer (the Forsta server when doing server-side
scripting) and Universal Coordinated Time (UTC). This number will be positive if you are behind UTC (e.g., Pacific
Daylight Time), and negative if you are ahead of UTC (e.g., Japan).
14.1.2.3.1. valueOf
dateObj.valueOf()
valueOf returns the stored time value in milliseconds since midnight, January 1, 1970 UTC.
Method Output
toUTCString
Sat, 1 Jan 2000 00:00:00 UTC
toLocalString
Friday, December 31, 1999 7:00:00
PM
toString
Fri Dec 31 19:00:00 EST 1999
There also exists a method called toGMTString, which returns a date converted to a string using Greenwich Mean
Time(GMT). This method is obsolete, and it is recommended that you use the toUTCString method instead.
- 187 -
Forsta v2022 Scripting Manual Forsta Confidential
- 188 -
Forsta Confidential Forsta v2022 Scripting Manual
returns the month part of the date as an integer in the range 1-12.
Important:
Note that this is different from the Date object, where getMonth and getUTCMonth return an integer in the
range 0-11.
dObj.year
returns the year part of the date as an integer (4 digits).
In this example we have an open text question and want the respondent to enter a date in the format YYYY-MM-DD.
We want to validate that the format is correct and that the date is a valid date, and also that the date is not after the
current date.
This can be done with the following script in the validation code field of the open text question (date1).
var d = IsDateFmt(f("date1").get(),"YYYY-MM-DD");
if(!d)
{
RaiseError();
SetQuestionErrorMessage(LangIDs.en,"Invalid date. Please correct using
the format YYYY-MM-DD");
}
else
{
var dt = new Date();
dt.setFullYear(d.year,d.month-1,d.day);
var current = new Date();
if(dt.valueOf() > current.valueOf())
{
RaiseError();
SetQuestionErrorMessage(LangIDs.en,"Please do not enter a date after
the current date.");
}
}
If the date provided is not valid, IsDateFmt(f("date1").get(),"YYYY-MM-DD") will return null. Used in a
condition null will yield the Boolean value false. If the date is valid, IsDateFmt will return an object. Used in a
condition this will yield true. So the first if condition, with !d , makes sure there will come an error message only
when the date is invalid or wrong format is used.
It is important that we include the rest of the script in an else branch because the properties year, month and day
are not defined if null is returned. So we need to make sure that that part of the script only is run when we have an
object in the variable d, to prevent script errors.
Then we introduce two instances of the Date object, and set one of them (dt) to the date answered, and the other
(current) to the current date. We use the setFullYear method to set the date. Observe that we have to subtract 1
from the month, since the Date object uses the integers 0-11 for month, whereas the month property in the object
returned from IsDateFmt uses the more conventional integers 1-12.
Validating that a Date with Drop-downs is within the next two Weeks
You can also set up the date with three questions, one for year, one for month and one for day. This can for example
be set up in a 3D grid with 3 grid questions as drop-downs like this:
- 189 -
Forsta v2022 Scripting Manual Forsta Confidential
Note: The codes of the questions must be numeric and the same as the legal year/month/day values. For
year the codes must be the full value (e.g. 2002), for month they must be numbers between 1 and 12, and for
day they must be numbers between 1 and 31 (see IsDateFmt and IsDate on page 146 for more information).
Let us say that we want to check that the answer is a valid date (so that e.g. February 30 th is not allowed), and that it
is a date in the next two weeks from the current date.
var d =
IsDate(f("day")["1"].get(),f("month")["1"].get(),f("year")["1"].get());
if(!d)
{
RaiseError();
SetQuestionErrorMessage(LangIDs.en,"Invalid date. Please correct.");
}
else
{
var dt = new Date();
dt.setFullYear
(d.year,d.month-1,d.day);
var current = new Date();
var limit = new Date();
limit.setDate(current.getDate()+14)
if(dt.valueOf() < current.valueOf() || dt.valueOf() > limit.valueOf())
{
RaiseError();
SetQuestionErrorMessage(LangIDs.en,"Please select a date within the
next two weeks.");
}
}
- 190 -
Forsta Confidential Forsta v2022 Scripting Manual
This script takes advantage of the fact that when using setDate, the month and possibly also year value will
automatically be updated if the value for date is outside the limit for the month. So if the result of
current.getDate()+14 is a number larger than the number of days in a month, limit will be set to a date in the
next month. For example, if current date is April 20th 2002, the limit will be 4th of May 2002 (April 20th + 14 days).
This will for example give this output if the answer on the date question was 2002-04-20:
- 191 -
Forsta v2022 Scripting Manual Forsta Confidential
If you have an open text question dob where respondents insert their date of birth, you can calculate the respondent’s
age and set it in a hidden question age with the following script, which is placed in the validation code of the question:
var d = IsDateFmt(f("dob").get(),"YYYY-MM-DD");
if(!d)
{
RaiseError();
SetQuestionErrorMessage(LangIDs.en,"Invalid date. Please use the format
YYYY-MM-DD");
}
else
{
var birthday = new Date();
birthday.setFullYear(d.year,d.month-1,d.day);
var today = new Date();
var years = today.getFullYear() - birthday.getFullYear();
birthday.setYear(today.getFullYear());
// If your birthday hasn't occurred yet this year, subtract 1.
if(today < birthday)
{
years-- ;
}
f("age").set(years);
}
Note: The Date question type is only available when using the Optimized Database format.
- 192 -
Forsta Confidential Forsta v2022 Scripting Manual
If you have an date question dob where respondents insert their date of birth, you can calculate the respondent’s age
and set it in a hidden question age with the following script, which is placed in the validation code of the question:
var birthday = new Date(f("dob").year(),f("dob").month()-
1,f("dob").day());
var today = new Date();
var years = today.getFullYear() - birthday.getFullYear();
birthday.setYear(today.getFullYear());
// If your birthday hasn't occurred yet this year, subtract 1
if(today < birthday)
{
years-- ;
}
f("age").set(years);
14.2.1. Properties
The properties of the Math object are different mathematical constants.
Math.E
Euler's constant, the base of natural logarithms. The E property is approximately equal to 2.718.
Math.LN2
The natural logarithm of 2. The LN2 property is approximately equal to 0.693.
Math.LN10
The natural logarithm of 10. The LN10 property is approximately equal to 2.302.
Math.LOG2E
The base-2 logarithm of e, Euler's constant. The LOG2E property is approximately equal to 1.442.
Math.LOG10E
The base-10 logarithm of e, Euler's constant. The LOG10E property is approximately equal to 0.434.
Math.PI
, the ratio of the circumference of a circle to its diameter, approximately 3.141592653589793.
Math.SQRT1_2
The square root of ½, or one divided by the square root of 2. The SQRT1_2 property is approximately equal to 0.707.
Math.SQRT2
The square root of 2. The SQRT2 property is approximately equal to 1.414.
- 193 -
Forsta v2022 Scripting Manual Forsta Confidential
Math.tan(x)
returns the tangent of a numeric expression x.
Math.acos(x)
returns the arc cosine of a numeric expression x.
Math.asin(x)
returns the arc sine of a numeric expression x.
Math.atan(x)
returns the arctangent of a numeric expression x.
Math.atan2(x,y)
Returns the angle of the polar coordinate corresponding to (x,y)
14.2.2.2. Rounding
Math.round(x)
returns a supplied numeric expression x rounded to the nearest integer. If the decimal portion of the number is 0.5 or
greater, the return value is equal to the smallest integer greater than the number. Otherwise, round returns the largest
integer less than or equal to the number. This is exactly as conventional rounding. For example, if we have a floating
point number between 0 and 2, values from 0 and up to but not including 0.5, will be rounded to 0. Values from and
including 0.5 and up to but not including 1.5 will be rounded to 1. Values from and including 1.5 up to and including 2,
will be rounded to 2.
Math.ceil(x)
returns the smallest integer greater than or equal to its numeric argument x, i.e. rounding up to the nearest integer.
For example, if we have a floating-point number between 0 and 2, the value 0 will be rounded to 0, and all values
greater than 0 and up to and including 1 will be rounded to 1. All values greater than 1 and up to and including 2 will
be rounded to 2.
Math.floor(x)
returns the greatest integer less than or equal to its numeric argument x, i.e. rounding down to the nearest integer.
For example, if we have a floating point number between 0 and 2, all values from 0 and up to, but not including 1, will
be rounded to 0. The value 1 and all values from 1 and up to but not including 2, will be rounded to 1, and the value 2
will be rounded to 2.
- 194 -
Forsta Confidential Forsta v2022 Scripting Manual
If we ask people to provide their yearly salary and we want to compute the monthly salary, this can be done by
dividing the yearly salary by 12. However this might result in a number with many decimals. If for example we want the
result with an accuracy of two digits and need to round it, we can do that by multiplying the result by 100, then do the
rounding, and then divide the result with 100. Let us say the yearly salary is in the question yearly and the monthly
salary should be stored in the question monthly. Then we can use a script as below to set the monthly value:
var yearly : int = f("yearly").toNumber();
var monthly : float = yearly/12;
f("monthly").set(Math.round(monthly*100)/100);
14.2.2.3. Random
Math.random()
returns a random number between 0 and 1 (float), e.g. 0.523. The number generated is from 0 (inclusive) to 1
(exclusive), that is, the returned number can be zero, but it will always be less than one.
This is an extremely powerful feature to use in your surveys when you want to pick responses randomly, or send
random respondents to different parts of the questionnaire. Combined with conditions and arithmetic operations you
can program extremely powerful solutions for the selections (see SetRandomCategories on page 88 for more
information).
toForm.set(selected);
In this script we pick responses from a set of available responses (the answers to the multi question brands, stored in
the variable available) and add them to the set stored in the variable selected. At the end we set the selected
answers in the random_brands multi.
If there number of responses is less than or equal to numberOfItems (here: 3), we obviously include all those
responses. But if there are more than 3 responses, we have to pick random responses from the answers given.
The random picking is done in this while loop:
- 195 -
Forsta v2022 Scripting Manual Forsta Confidential
Important
Math.floor must be used, not Math.round or Math.ceil. Using Math.floor is the only way to ensure
that the probability of selecting the indexes is the same for all of them and that you get no errors.
Math.round would extend the set of possible picks with the index codes.length (i.e. the number 4 in our
example). This would cause problems because 4 is not an index in the array. If we used Math.ceil, we would round
up to the numbers 1,2,3 and 4, and could subtract 1 from these numbers to get the index. However, even though the
probability of this happening is extremely small, there is a small chance the number 0 would be returned from
Math.random(). And using Math.ceil on 0 would yield 0, and this would again cause problems.
In our example, where randomNumber was calculated to 2.5132, randomIndex will get the value 2.
codes[2] is "4", so the code 4 will be removed from the available set and added to the selected set.
The while loop will now continue to the next iteration with the remaining three codes, so in our example codes will be
have the following items in the next iteration:
codes[0] = "1"
codes[1] = "3"
codes[2] = "8"
Then the script will randomly pick one of these, and continue with this process until 3 items are selected.
Picking random items like this is best suited for surveys where the respondent is not allowed to modify previous
answers. If the respondent goes back to the brands question and then forwards again, the script is run again, possibly
resulting in a different set. So then the respondent will get questions for other brands. This may be confusing and
cause irritation for the respondent.
- 196 -
Forsta Confidential Forsta v2022 Scripting Manual
- 197 -
Forsta v2022 Scripting Manual Forsta Confidential
pow returns the value of a base expression taken to a specified power, baseexponent.
Math.sqrt(number)
Returns the square root of a numeric expression number. If number is negative, the return value is zero.
14.3.1. Constructors
An instance of the String object can be created like this:
newString = new String({"stringLiteral"});
The curly brackets are used to indicate that the string literal is optional.
String objects can also be created implicitly using string literals.
newString = "{stringLiteral}";
or
newString : String = "{stringLiteral}";
14.3.2. Properties
strVariable.length
"String Literal".length
length returns the length of a String object, an integer with the number of characters in the String object.
14.3.3. Index
Many of the methods of the String object refer to index on a string. The index is used to refer to a characters
position within a string. If you have the string
0 1 2 3 4 5 6 7 8 9101112131415
"This is a string"
the character a has index 8, because the index starts at 0 for first character. The index of the last character will always
be 1 less than the string's length. This is similar to indexing in arrays.
- 198 -
Forsta Confidential Forsta v2022 Scripting Manual
strObj.charCodeAt(index)
charCodeAt returns an integer representing the Unicode encoding of the character at the specified index. index is
a number between 0 and the length of the string minus 1. If there is no character at the specified index, NaN is
returned.
- 199 -
Forsta v2022 Scripting Manual Forsta Confidential
returns the character position of the last occurrence of a subString within a String object. startIndex is
optional, and is an integer value specifying the index to begin searching within the String object. If omitted,
searching begins at the end of the string. If the subString is not found, a-1 is returned.
If startIndex is negative, startIndex is treated as zero. If it is larger than the greatest character position index, it
is treated as the largest possible index.
Searching is performed right to left.
- 200 -
Forsta Confidential Forsta v2022 Scripting Manual
stingObj.substring(start, end)
returns the substring at the specified location within a String object.
start is the index indicating the beginning of the substring and end is the index indicating the end of the substring.
The substring method returns a string containing the substring from start up to, but not including, end.
The substring method uses the lower value of start and end as the beginning point of the substring. For
example, stringObj.substring(0,3) and stringObj.substring(3,0) return the same substring.
If either startor end is NaN or negative, it is replaced with zero.
The length of the substring is equal to the absolute value of the difference between start and end. For example,
the length of the substring returned in stringObj.substring(0,3) and strObj.substring(3,0) is three.
if(form.size() > 1)
{
body = body.substring(0,body.lastIndexOf(",")) + " and " +
body.substring(body.lastIndexOf(",")+1,body.length);
}
SendMail("[email protected]",f("email"),"Answers",body);
If there are two answers or more, the answers string will be set to the substring from the beginning of the answers
string to (but excluding) the last comma, the string " and " and the substring from the character after the last
comma to the end of the answers string.
- 201 -
Forsta v2022 Scripting Manual Forsta Confidential
Method Equivalent to
- 202 -
Forsta Confidential Forsta v2022 Scripting Manual
• Test for a pattern within a string. For example, you can test an input string to see if a telephone number
pattern or a credit card number pattern occurs within the string.
• Replace text. You can use a Regular Expression to identify specific text in a string and either remove it
completely or replace it with other text.
• Extract a substring from a string based upon a pattern match.
The syntax of Regular Expressions is not easy to understand. If you have problems understanding it, you are advised
to check the examples, try to modify them and test what the differences are. The Perl scripting language popularized
Regular Expressions, and JScript 's support of Regular Expressions is based on that of Perl. So for further reading
about Regular Expressions, you may search for Perl documentation in addition to JScript . NET documentation.
Regular Expressions are implemented as Regular Expression objects, and are created as follows:
var re = /pattern/{flags};
(similar to Regular Expressions in Perl) or
var re = new RegExp("pattern",{"flags"});
(similar to normal syntax for instantiating an object in JScript .NET)
pattern is the pattern to be matched and the optional flags is a string containing i, and/or m. The i stands for
ignore case and the m for multi-line search.
Important
When defining a Regular Expression with the syntax /pattern/flags, do not use quotation marks around
the strings. However when using the other notation you must use them.
- 203 -
Forsta v2022 Scripting Manual Forsta Confidential
Special Comment
Character
$ Matches the position at the end of an input string. If the multi-line (m) property is set, $ also matches
the position preceding \n or \r. (newline or carriage return).
() Marks the beginning and end of a sub expression. Sub expressions can be captured for later use.
- 204 -
Forsta Confidential Forsta v2022 Scripting Manual
? Matches the preceding sub expression zero or one time, or indicates a "non-greedy" quantifier.
\ Marks the next character as a special character, a literal, a back-reference, or an octal escape.
^ Matches the position at the beginning of an input string except when used in a bracket expression
where it negates the character set. If the multi-line property is set, ^ also matches the position
following \n or \r (newline or carriage return).
Expression Matches
\$ $
\( (
\) )
\* *
\+ +
\. .
\[ [
\? ?
\\ \
\^ ^
\{ {
\| |
/Forsta\?/
matches the string "Forsta?"
- 205 -
Forsta v2022 Scripting Manual Forsta Confidential
Character Meaning
\s Matches any white space character including space, tab, form-feed, etc.
- 206 -
Forsta Confidential Forsta v2022 Scripting Manual
When a range is specified in this manner, both the starting and ending values are included in the range. It is important
to note that the starting value must precede the ending value in Unicode sort order.
If you want to include the hyphen character (-) in your bracket expression, you must do one of the following:
Escape it with a backslash:
[\-]
Put the hyphen character at the beginning or the end of the bracketed list. The following expressions match all
lowercase letters and the hyphen:
[-a-z][a-z-]
Create a range where the beginning character value is lower than the hyphen character and the ending character
value is equal to or greater than the hyphen. Both of the following Regular Expressions satisfy this requirement:
[!--][!-~]
i.e. characters from ! to – or from ! to ~.
If you want to find all the characters not in the list or range, you can place the caret (^) character at the beginning of
the list. If the caret character appears in any other position within the list, it matches itself, that is, it has no special
meaning. The following Regular Expression matches chapter headings with numbers different from 1,2,3,4 and 5 (and
any other characters different from 1,2,3,4 and 5):
/Chapter [^12345]/
The same expressions above can be represented using the hyphen character (-).
/Chapter [^1-5]/
A typical use of a bracket expression is to specify matches of any upper- or lowercase alphabetic characters or any
digits. The following JScript .NET expression specifies such a match:
/[A-Za-z0-9]/
Character Description
[^a-z] A negative range characters. Matches any character not in the specified
range.
14.4.1.5. Quantifiers
Sometimes, you don't know how many characters there are to match. In order to accommodate that kind of
uncertainty, Regular Expressions support the concept of quantifiers. These quantifiers let you specify how many
times a given component of your Regular Expression must occur for your match to be true.
The following table illustrates the various quantifiers and their meanings:
Character Description
- 207 -
Forsta v2022 Scripting Manual Forsta Confidential
{n,m} Matches at least n and at most m times. m and n are non-negative integers, where n <= m.
14.4.1.6. Anchors
All the examples so far have recognized patterns anywhere in a string. But you may want the patterns to match only if
they e.g. appear at the beginning of the string. Anchors provide that capability.
Anchors allow you to fix a Regular Expression to either the beginning or end of a string. They also allow you to create
Regular Expressions that occur either within a word or at the beginning or end of a word. The following table contains
the list of Regular Expression anchors and their meanings:
Character Description
^ Matches the position at the beginning of the input string. If the multi-line property is set, ^ also
matches the position following \n or \r (newline or carriage return).
$ Matches the position at the end of the input string. If the multi-line property is set, $ also
matches the position preceding \n or \r (newline or carriage return).
\b Matches a word boundary, that is, the position between a word and a space.
You cannot use a quantifier with an anchor. Since you cannot have more than one position immediately before or after
a newline or word boundary, expressions such as ^* are not permitted.
To match text at the beginning of a line of text, use the ^ character at the beginning of the Regular Expression. This is
different from using the ^ within a bracket expression.
To match text at the end of a line of text, use the $ character at the end of the Regular Expression.
- 208 -
Forsta Confidential Forsta v2022 Scripting Manual
To use anchors when searching for chapter headings, the following JScript .NET Regular Expression matches a
chapter heading with up to two following digits that occur at the beginning of a line and where there is no text after the
heading:
/^Chapter [1-9][0-9]?$/
Matching word boundaries is a little different but adds a very important capability to Regular Expressions. A word
boundary is the position between a word and a space. A non-word boundary is any other position. The following
JScript .NET expression matches the first three characters of the word 'Chapter' because they appear following a
word boundary:
/\bCha/
The position of the '\b' operator is critical here. If it's positioned at the beginning of a string to be matched, it looks for
the match at the beginning of the word; if it's positioned at the end of the string, it looks for the match at the end of the
word. For example, the following expressions match 'ter' in the word 'Chapter' because it appears before a word
boundary:
/ter\b/
- 209 -
Forsta v2022 Scripting Manual Forsta Confidential
A positive lookahead, specified using ?=, matches the search string at any point where a matching Regular
Expression pattern in parentheses begins.
A negative lookahead, specified using ?!, matches the search string at any point where a string not matching the
Regular Expression pattern begins.
If you want to search for the protocol in a url like "http://www.confirmit.com", but only if it ends with .com:
/^[^:]+(?=.*\.com$)/
Because of the anchor ^, the match is found at the beginning of the string. Then the first part
[^:] +
searches for one or more characters different from :. One or more because of the quantifier +, different from : because
of the bracket expression [^:]
Then there is a positive lookahead:
(?=.*\.com$)
which searches through the string to find a match for
.* \.com$
Because of the anchor $ this has to be at the end of the string. . matches any character except the newline character,
and because of the quantifier * we can have 0 or more of these characters before the last part, which is the character .
(which has to be escaped with backslash \) followed by com – i.e. ".com".
But the match will be for the first part of the string, i.e. "http" in "http://www.confirmit.com".
Similarly, the expression
/^[^:]*(?!.*\.edu$)/
will search for the first characters until : is reached in a string not ending with ".edu".
Character Description
Matches pattern and captures the match. The captured match can be retrieved from the
(pattern)
resulting Matches collection, using the $0...$9 properties in JScript .NET.
(?:pattern) Matches pattern but does not capture the match (it is not stored for possible later use).
Positive look-ahead matches the search string at any point where a string-matching pattern
begins. The match is not captured for possible later use. After a match occurs, the search for
(?=pattern)
the next match begins immediately following the last match, not after the characters that
comprised the look-ahead.
Negative look-ahead matches the search string at any point where a string not matching
pattern begins. The match is not captured for possible later use. After a match occurs, the
(?!pattern)
search for the next match begins immediately following the last match, not after the characters
that comprised the look-ahead.
14.4.1.8. Back-References
You can store a part of a matched pattern for later reuse. Placing parentheses around a Regular Expression pattern
or part of a pattern causes that part of the expression to be stored into a temporary buffer.
Each captured sub-match is stored as it is encountered from left to right in a Regular Expressions pattern. The sub-
matches are numbered beginning at 1 and continuing up to a maximum of 99 sub-matches. Each different buffer can
be accessed using
- 210 -
Forsta Confidential Forsta v2022 Scripting Manual
\n
where n is one or two decimal digits identifying a specific buffer, e.g. \1.
For example, back-references can be used to check for double occurrences of the same words, e.g. in a string such
as:
Scripting is is fun!
The following JScript .NET Regular Expression uses a single sub-expression to check for duplicates:
/\b([a-z]+) \1\b/gim
The sub-expression is everything between parentheses. That captured expression includes one or more alphabetic
characters, as specified by [a-z]+. The second part of the Regular Expression (\1) is the reference to the previously
captured sub-match, that is, the second occurrence of the word. \b is used for word boundary, so that the check is
done on complete words.
Character Description
Character Description
Identifies either an octal escape value or a back-reference (see Back-References on page 210
\num
for more information).
Since \ followed by a number num can represent both octal escape values and back-references, the following rules
apply:
If num has one digit and \num is preceded by at least num captured sub expressions, num is a back-reference.
Otherwise, num is an octal escape value if num is an octal digit (0-7).
- 211 -
Forsta v2022 Scripting Manual Forsta Confidential
If num has two digits and \num is preceded by at least num captured sub expressions, num is a back-reference. If the
first digit is n, and \num is preceded by at least n captures, n is a back-reference followed by a literal, the second
digit. If neither of these applies, \num matches an octal escape value when the number is an octal (both digits in the
range 0-7).
If num has three digits, it matches an octal escape value when the first digit is 0-3 and the two last digits are octal
digits (0-7).
Operator(s) Description
\ Escape
| Alternation
- 212 -
Forsta Confidential Forsta v2022 Scripting Manual
Let us say you want the respondent to specify his phone number in a particular format, allowing a digit or + as the first
character and spaces between number sets, but no other characters. The following validation code uses a Regular
Expression to check the formatting of the phone number, provided that the phone number is applied in an open text
question with question ID phone:
var num : String = f("phone").get();
var re = /^(?:\d|\+)(?:\d| )+$/;
if(!re.test(num))
{
RaiseError();
SetQuestionErrorMessage(LangIDs.en,"Please provide your phone number,
only using digits and space, and with + before your country code if it is
a foreign number.");
}
The Regular Expression starts the search at the beginning of the string (^). Then the first character should be either a
digit or + (?:\d|\+). Because of ?: this sub expression is not stored. Then the rest of the string consists of one or more
digits or spaces (?:\d| ) until the end of the string is reached ($).
In this script there are no restrictions on number of spaces or digits.
Exercise 8: Restricting the Number of Digits in a Phone Number
Based on the previous example, please modify the Regular Expression so that it checks that the phone number is on
the format xxx xxx xxxx – i.e. 3 groups of 3+3+4 digits separated with space. (This time with no + for country code).
The answer is given in APPENDIX A Answers to Exercises.
- 213 -
Forsta v2022 Scripting Manual Forsta Confidential
If you want to send an email and in the email text list the answers to a multi question from the survey, you can use
categoryLabels. Converted into a string this will give the items separated by commas. If you want to have the
answers on one line each instead of separated by commas you have to replace the commas with line breaks. If the
email is sent as plain text, you then have to replace the commas with the special character \n.
This script will replace the commas in a listing of the answers given on a multi question brands:
var body : String = "";
body += "Here are the answers on the brands question:\r\n\r\n"
body += brandsAnswers
SendMail("[email protected]",f("email"),"Answers",body);
If the mail is sent as HTML, you have to replace the commas with the HTML <br> tag instead:
var body : String = "";
body += "Here are the answers on the brands question:<br><br>"
body += brandsAnswers
SendMail("[email protected]",f("email"),"Answers",body,"","",0,0)
;
- 214 -
Forsta Confidential Forsta v2022 Scripting Manual
Make a script to validate a US zip code. Question ID: zipcode. US zip codes are 5 digit codes. So it is tempting to set
up a numeric question with total digits 5, and let the default validation do the work. However, the first number can be a
zero (0), and to make sure that it is not removed when the value is stored (as it would for numeric questions), the
question should be set up as an open text question with field width 5 instead of as a numeric. The easiest way to
validate that all 5 characters are digits, is to use a Regular Expression.
The answer is given in APPENDIX A Answers to Exercises.
Combining arrays with codes answered on two questions into one array
If you have two multi questions and would like to create an array consisting of all the codes answered on the two multi
questions, one possible way is to combine the two arrays you get from the categories method:
var q8 = f('q8').categories();
var q9 = f('q9').categories();
var codes = q8.concat(q9);
- 215 -
Forsta v2022 Scripting Manual Forsta Confidential
join returns a string value consisting of all the elements of an array concatenated and separated by the specified
separator character. If separator is omitted, the array elements are separated with a comma. If any element of the
array is undefined or null, it is treated as an empty string ("").
array.toString()
array.valueOf()
Both toString and valueOf converts elements of an array to strings. The resulting strings are concatenated, separated
by commas. This is the same as using join without specifying a separator (or specifying comma as separator).
body += brandsAnswers
SendMail("[email protected]",f("email"),"Answers",body);
If the mail is sent as HTML, you must replace the commas with the HTML <br> tag:
var body : String = "";
body += "Here are the answers on the brands question:<br><br>"
body += brandsAnswers
SendMail("[email protected]",f("email"),"Answers",body,"","",0,0)
;
- 216 -
Forsta Confidential Forsta v2022 Scripting Manual
reverse returns an Array object with the elements reversed. The method reverses the elements of the Array
object in place (array). It does not create a new Array object during execution. If the array is not contiguous, the
reverse method creates elements in the array that fill the gaps in the array. Each of these created elements has the
value undefined.
array.sort({this.sortFunction})
sort returns an Array object with the elements sorted. sortFunction is optional and is the name of the function
used to determine the order of the elements. Because Forsta script nodes are wrapped inside a class, you have to
use the keyword this to refer to the current instance (this.sortFunction). If the sorting function is omitted, the
elements are sorted in ascending, ASCII character order. The sort method sorts the Array object in place; no new
Array object is created during execution.
If you supply a function in the this.sortFunction argument, it must return one of the following values:
• A negative value if the first argument passed is less than the second argument.
• Zero if the two arguments are equivalent.
• A positive value if the first argument is greater than the second argument.
In a question such as this, the "other, specify" items will usually not be required, whereas the remaining items will be
required. To achieve this, we must set the "Not required" property on the grid question, and provide our own validation
code instead.
There should also be validation checking that text is provided if a rating is provided for an "other, specify" field and
vice versa. For this, the standard "Other Specify Checking" can be used (just ensure it is turned on when generating
web interview files). However, if the respondent accidentally rates one of the "other" items, there is no way for the
respondent to unselect that row. We must therefore include a removal of the radio button selection for the "other"
items when they are not answered correctly.
Here is the answer list of this question with codes used:
- 217 -
Forsta v2022 Scripting Manual Forsta Confidential
var notAnswered = new Array(); //array to hold text of not answered items
for(i=0;i<codes.length;i++)
{
code = codes[i];
if(form[code].toBoolean() && !f("q1_"+code+"_other").toBoolean())
{
//remove answer
form[code].set(null);
}
}
if(notAnswered.length > 0)
{
RaiseError();
SetQuestionErrorMessage(LangIDs.en,"Please answer for all providers.
Answers are missing for:<br>"+notAnswered.toString());
}
//helper function for sorting
function NumSort(a,b)
{
var x = parseInt(a,10);
var y = parseInt(b,10);
return x-y;
}
- 218 -
Forsta Confidential Forsta v2022 Scripting Manual
This example uses the push method to add elements to the end of an array. We use the sort method to sort the
array. When the codes array is set with the statement
var codes = a("q1").diff(set("97","98")).members();
it is built from set expressions, and as we have learnt the order of the items within a set is insignificant. So the order
the elements come in the array after using this expression is not necessarily the same order as in the answer list. To
make sure we get them in the same order as in the answer list, so the listing in the error message does not become
confusing to the respondents, we use the sort method with the helper function NumSort that converts its parameters
(the codes in the array) to numbers and then do subtraction and return the result. If the result is negative, the first
code is less than the second, if it is 0 they are equal and if the result is positive the first one is greater than the
second. This is just as the description of the sortFunction above.
- 219 -
Forsta v2022 Scripting Manual Forsta Confidential
• Answer required checks - All questions (except for ordinary multi questions without an exclusive item ("None
of the above")) are by default required. You can set a question to be "Not required" in the properties of the
question, or you can turn off the checking for all questions by deselecting "Answer required checks" when
generating WI.
• Exclusivity tests - An "exclusive item" in the answer list of a multi question is an answer alternative with the
"single punch" property set. (Typically a "None of the above" or "Don't know" answer alternative.) This means
that the answer alternative cannot be answered in combination with any of the other items. The exclusivity
check makes sure that the question has at least one answer, and that no exclusive item is selected in
combination with other answers. This checking can be turned off by deselecting "Exclusivity tests" when
generating WI.
• Other-specify checking - When the "other" property is set for an item in an answer list, a text box is included
next to that item. The "other-specify" checking makes sure that there is a correspondence so that the text box
has an answer only if that answer alternative is selected and visa versa. It can be turned off globally by
deselecting "Other-specify checking" when generating WI.
• Rank order tests - For a ranking question or a grid question with the "ordered" property set, the system
checks that the answers constitute a set of consecutive integers starting at 1, and that all items have a rank.
This default checking can be turned off globally by deselecting "Rank order tests".
• Answer size tests for fixed-width fields - If a field width is defined for a question, the system checks that the
respondent's answer is within the limit. This cannot be turned off globally, because the database is set up
according to the field width definitions, so the database cannot accept answers above this limit.
• Numeric validation - For numeric and numeric list questions, the system checks that the answer consists of
the symbols 0 to 9 only, and is within the limits defined in total digits, decimal places as well as lower and
upper limit. This validation cannot be turned off globally because the database is set up according to these
settings and cannot accept non-numeric answers that do not correspond to these settings.
All of these types of validation have their own error messages provided in Forsta. These error messages are provided
in a number of languages, but are the same for all users of an installation. They can be changed globally on a Forsta
server installation, but not for individual surveys.
If you want something other than the standard error messages, you must add code in the validation code field of the
question where the validation applies. This chapter explains a number of functions that make it easier to build
customized error messages for the default answer checks.
Function Description
QuestionErrors()
returns true if an error has been raised during any validation, false otherwise.
MissingRequiredError()
returns true if one or more required answers to a question are missing, false
otherwise.
ExclusivityError()
returns true if an exclusive answer ("single punch") in a multi has been selected
together with any other alternative, false otherwise.
- 220 -
Forsta Confidential Forsta v2022 Scripting Manual
NotSpecifiedError()
returns true if an alternative in an Other-Specify construct has been
selected/answered without filling in the associated "Specify" text box, false
otherwise.
NotSelectedError()
returns true if a "Specify" value has been entered in the text box of an Other-Specify
construct without selecting/answering the associated alternative, false otherwise.
RankError()
returns true if the "Ordered" property has been selected for the form and the
answers to the questions are non-numeric, do not start at 1 or are non-consecutive,
false otherwise.
SizeError()
returns true if one or more open-ended answers exceeded the maximum length
specified in field width, false otherwise.
NumericError()
returns true if the “Numeric” property has been selected and the answer is not
numeric, false otherwise.
PrecisionError()
returns true if the “Numeric” property has been selected and the answer cannot be
stored within the defined total digits, false otherwise.
ScaleError()
returns true if the “Numeric” property has been selected and the answer contains
more decimals than in the defined decimal places, false otherwise.
RangeError()
returns true if the “Numeric” property has been selected and the answer is outside
the defined range, false otherwise.
PasswordError() used on a opentext panel variable with the password property set. Returns true if
any of the password validation settings for the panel (in panel settings) have not
been satisfied.
Example:
if(MissingRequiredError())
{
SetQuestionErrorMessage(LangIDs.en,"Please provide an answer.");
}
When one of these functions returns true, an error situation has already been flagged, so you do not have to use the
RaiseError function.
- 221 -
Forsta v2022 Scripting Manual Forsta Confidential
Templates are available for all the standard validation. There are usually several versions of the templates, which
differ in how they separate words when they are listed. Some only use commas, some use commas, but "and" or "or"
between the last two items. "and"/"or" is also available in several languages, so e.g. in German they will be replaced
with "und"/"oder" and so on.
Template Description
MISSING
Labels of all questions that lack answers, comma separated.
MISSING_AND
Same as above, but with the word “and” separating the two last items.
MISSING_OR
Same as above, but with the word “or” separating the two last items.
Example:
if(MissingRequiredError())
{
SetQuestionErrorMessage(LangIDs.en,
ErrorTemplate("Please select an answer for ^MISSING_AND^."));
}
Template Description
SEL_EXCL
The labels of all exclusive (single punch) answers that were selected.
SEL_EXCL_AND
Same as above, but with the word “and” separating the two last items.
SEL_EXCL_OR
Same as above, but with the word “or” separating the two last items.
SEL_NEXCL
The labels of all non-exclusive (multi punch) answers that were selected.
SEL_NEXCL_AND
Same as above, but with the word “and” separating the two last items.
SEL_NEXCL_OR
Same as above, but with the word “or” separating the two last items.
DEF_EXCL
The labels of all exclusive (single punch) answers, regardless of which of them that were
selected.
- 222 -
Forsta Confidential Forsta v2022 Scripting Manual
DEF_EXCL_AND
Same as above, but with the word “and” separating the two last items.
DEF_EXCL_OR
Same as above, but with the word “or” separating the two last items.
DEF_NEXCL
The labels of all non-exclusive (multi punch) answers, regardless of which of them that
were selected.
DEF_NEXCL_AND
Same as above, but with the word “and” separating the two last items.
DEF_NEXCL_OR
Same as above, but with the word “or” separating the two last items.
Examples:
if(ExclusivityError())
{
SetQuestionErrorMessage(LangIDs.en,
ErrorTemplate("Please do not check ^SEL_EXCL_OR^ if you check other
answers to the question."));
}
if(ExclusivityError())
{
SetQuestionErrorMessage(LangIDs.en,
ErrorTemplate("^DEF_EXCL_AND^ can not be combined with any of the other
answers."));
}
NotSpecifiedError()
returns true if an alternative in an Other-Specify construct has been selected/answered without filling in the associated
"Specify" text box.
NotSelectedError()
returns true if a "Specify" value has been entered in the text box of an Other-Specify construct without
selecting/answering the associated answer alternative.
The following template elements are defined when one of these functions returns true:
Template Description
OTHER
Label of the alternative/input that requires specification in an Other-Specify construct.
SPEC
The specification
Examples:
- 223 -
Forsta v2022 Scripting Manual Forsta Confidential
if(NotSpecifiedError())
{
SetQuestionErrorMessage(LangIDs.en,ErrorTemplate("Please specify if
^OTHER^ is chosen."));
}
if(NotSelectedError())
{
SetQuestionErrorMessage(LangIDs.en,
ErrorTemplate("If you specify ^OTHER^ then please select the ^OTHER^
option."));
}
Template Description
RANK_MIN
The label of the first member of the ranking scale, or 1 if the question is open ended.
RANK_MAX
The label of the nth member of the ranking scale, or n if the question is open ended, where n is
the number of items to rank.
Example:
if(RankError())
{
SetQuestionErrorMessage(LangIDs.en,
ErrorTemplate("Please enter consecutive answers in the range ^RANK_MIN^
to ^RANK_MAX^."));
}
Template Description
TOO_LONG
The labels of the inputs that were too long.
TOO_LONG_AND
Same as above, but with the word “and” separating the two last items.
MAX_SIZE
The maximum allowed size.
Example:
- 224 -
Forsta Confidential Forsta v2022 Scripting Manual
if(SizeError())
{
SetQuestionErrorMessage(LangIDs.en,
ErrorTemplate("The answers to ^TOO_LONG_AND^ were longer than
^MAX_SIZE^ characters and have been truncated. Please review."));
}
Template Description
NUMERIC_ERRORS
The labels of all elements with a numeric error.
NUMERIC_ERRORS_AND
Same as above, but with the word “and” separating the two last items.
Example:
if(NumericError())
{
SetQuestionErrorMessage(LangIDs.en,
ErrorTemplate("Please make sure that the answers to ^NUMERIC_ERRORS^
are numbers only."));
}
Template Description
PRECISION
The defined total digits
PRECISION_ERRORS
The labels of all elements with a total digits error.
PRECISION_ERRORS_AND
Same as above, but with the word “and” separating the two last items.
Example:
if(PrecisionError())
{
SetQuestionErrorMessage(LangIDs.en,
ErrorTemplate("Please enter a number with no more than ^PRECISION^
digits for ^PRECISION_ERRORS^."));
}
- 225 -
Forsta v2022 Scripting Manual Forsta Confidential
Template Description
SCALE
The defined decimal places
SCALE_ERRORS
The labels of all elements with to many decimals.
SCALE_ERRORS_AND
Same as above, but with the word “and” separating the two last items.
Example:
if(ScaleError())
{
SetQuestionErrorMessage(LangIDs.en,
ErrorTemplate("Please enter answers with no more than ^SCALE^ decimals
for ^SCALE_ERRORS_AND^."));
}
Template Description
RANGE_MIN
The label of the defined minimum value.
RANGE_MAX
The label of the defined maximum value.
RANGE_ERRORS
The labels of all elements with too many decimals.
RANGE_ERRORS_AND
Same as above, but with the word “and” separating the two last items.
Example:
if(RangeError())
{
SetQuestionErrorMessage(LangIDs.en,
ErrorTemplate("Please enter answers in the range ^RANGE_MIN^ to
^RANGE_MAX^."));
}
- 226 -
Forsta Confidential Forsta v2022 Scripting Manual
Note: If the survey is using a responsive layout, the client-side validation (which does not have details of
numeric range boundaries) is executed before any custom validation. These template elements will therefore
not function and the default error messages will be presented.
Template Description
CTITLE
The column header (question text) for the question in the 3D grid.
Example:
if(f("q1").size() < 5)
{
SetQuestionErrorMessage(LangIDs.en,
ErrorTemplate("Please select at least 5 items for ^CTITLE^."));
}
- 227 -
Forsta v2022 Scripting Manual Forsta Confidential
16.1. Request
Information can be sent in to the server from the user either from a web form (as the questions in the survey), passed
in with the web address URL or stored in a cookie. This, as well as other information about the incoming request can
be retrieved using the Request object.
We will look into some of the properties of the Request object. All of these return values of the type
NameValueCollection. This is a type that represents a sorted collection of associated String keys and String
values that can be accessed either with the key or with the index (integer from 0). This means that their values can be
referenced in the same way as you refer to values in an Array (see Arrays on page 39 for more information), but also
using their String key, for example:
var aValue = Request("arg");
This will look through all values sent in with the request to find a key that matches the name specified in argand
return the corresponding value. If there is no match for arg, null will be returned. This means that you can use the
expression
Request("arg")!=null
to check if it exists before using the value returned.
Note: Survey links in hitlists can have parameters added to the link. Two functions are available to receive the
value from the link; Request and UserParameters (see UserParameters on page 89 for more information). The
function you must use depends on the link's “Link type” setting. Request() will only be able to retrieve the
value from the hitlist link when "Link type" in the Hitlist Field Properties page is set to "Unencrypted URL
parameters". Refer to the separate Reportal User Guide for further details.
A more robust approach than using the Request object directly is to use the separate properties of the Request
object to prevent naming conflicts. In the next chapters we will describe some of the most useful properties.
Note: Request and Request.Form are not supported by CAPI or AskMe App. Use RequestForm (see
RequestForm on page 228 for more information).
16.1.1. Request.Form
Request.Form
will give the collection of form values submitted using "POST".
16.1.2. RequestForm
RequestForm
This was created because Request.Form and Request are not supported by CAPI or AskMe App. RequestForm
functions in the same way as Request.Form (see Request.Form on page 228 for more information).
16.1.3. QueryString
Request.QueryString()
will give the collection of values supplied on the URL or from a form submitted with "GET". If you want to send values
into the survey with the url, they can be included after the question mark after project_ID.aspx, separated by
ampersands (&), e.g.
http://survey.confirmit.com/wix/project_ID.aspx?variable1=value1&variable2
=value2
The keys here are variable1 and variable2, so using the key variable1 as in
- 228 -
Forsta Confidential Forsta v2022 Scripting Manual
Request.QueryString("variable1")
with the url above will return the value value1.
16.1.4. Request.Cookies
Request.Cookies
will return the cookies stored from the of the Forsta server domain. It returns an HttpCookieCollection object (see
Cookies on page 232 for more information).
16.1.5. ServerVariables
Request.ServerVariables
will give the information sent in the header or internal server values.
Here is a table listing an extract of the possible server variables in the collection returned from the
ServerVariables property:
Variable Meaning
ALL_HTTP
All HTTP headers sent by the client., with their names capitalized and
prefixed with HTTP_
ALL_RAW
Retrieves all headers in raw form (the form they were sent to the
server by the client).
CONTENT_LENGTH
The length of the content as given by the client.
CONTENT_TYPE
The MIME type of the request, such as www-url-encoded for a form
being posted to the server.
GATEWAY_INTERFACE
The Common Gateway Interface (CGI) supported on the server.
HTTP_<HeaderName>
The value stored in the header HeaderName. Any header other than
those listed in this table must be prefixed by HTTP_ in order for the
ServerVariables collection to retrieve its value. Note that the server
interprets any underscore (_) characters in HeaderName as dashes in
the actual header. For example if you specify HTTP_MY_HEADER,
the server searches for a header sent as MY-HEADER.
HTTP_ACCEPT
The MIME types the client can accept.
HTTP_ACCEPT_LANGUAGE
The languages accepted by the client.
HTTP_ACCEPT_ENCODING
The compression encoding types supported by the client.
HTTP_CONNECTION
Indicates whether the connection allows keep-alive functionality.
HTTP_COOKIE
Returns the cookie string that was included with the request.
HTTP_USER_AGENT
Returns a string describing the browser that sent the request. See
below for an example.
- 229 -
Forsta v2022 Scripting Manual Forsta Confidential
HTTPS Returns "On" if HTTPS was used for the request and "Off" if not.
HTTPS_KEYSIZE
Number of bits in the encryption used to make the HTTPS connection.
For example, 128.
HTTPS_SECRETKEYSIZE
Number of bits in server certificate private key. For example, 1024.
HTTPS_SERVER_ISSUER
Issuer field of the server certificate.
HTTPS_SERVER_SUBJECT
Subject field of the server certificate.
LOCAL_ADDR
The IP address of the server which is handling the request.
QUERY_STRING
Query information stored in the string following the question mark (?)
in the HTTP request.
REMOTE_ADDR
The IP address of the remote host making the request.
REMOTE_HOST
The host name of the client making the request, if available.
REQUEST_METHOD
The type of the HTTP request made: "GET", "POST" or "HEAD".
SERVER_NAME
The server's host name,
SERVER_PORT
The port number to which the request was sent.
SERVER_PORT_SECURE
A string that contains either 0 or 1. If the request is being handled on
the secure port, then this will be 1. Otherwise, it will be 0.
SERVER_PROTOCOL
The HTTP protocol and version in use on the server.
SERVER_SOFTWARE
The name and version of the web server software running on the
server.
- 230 -
Forsta Confidential Forsta v2022 Scripting Manual
To set this hidden question based on the values sent in with the URL, use the code given below in a script node at the
beginning of the questionnaire.
f("source").set(Request("site"));
Alternatively, you can use the QueryString property:
f("source").set(Request.QueryString("site"));
Important
The script node with Request must be the first node in the questionnaire, because once the respondent
moves to the next page, the values are lost.
Now source can be used for reporting, quotas, logic etc. in the same way as an ordinary question.
16.2. Response
Response is used to write content to the client (the respondent's browser), including headers and cookies. Here we
will only cover the Write method and the property used to set cookies.
16.2.1. Write
Response.Write(arg)
You may use the Write method for debugging purposes, for example to get values of variables you are using in your
script written to the screen when testing to help identifying why the script does not work as intended. For other
purposes it is recommended to use response piping with ^-s inside one of the text fields of a question or an info
instead, since you will then have better control of where on the page the text you output is placed.
arg can be any type of object, as it will be converted to a string when written to the client.
- 231 -
Forsta v2022 Scripting Manual Forsta Confidential
16.2.2. Cookies
Response.Cookies
The Cookies property indicates the cookies collection, which allows addition of cookies to the outgoing stream,
adding cookies to the client from a Forsta survey. It can for example be used to prevent respondents of an open
survey from taking the survey more than once, as showed in the example below.
The class HttpCookiesCollection provides a wrapper for a collection of cookies. You use this to set and modify
properties and values in the cookies. Most useful for us is the Add method:
cookiesCollection.Add(ccokie)
The Add method allows the addition of a single cookie to the collection. The parameter cookie is an object of the
HttpCookie class. HttpCookie has two different constructors:
varcookie = new HttpCookie(string);
which creates and names a new cookie.
varcookie = new HttpCookie(string1, string2);
which creates, names (string1), and assigns a value (string2) to a new cookie.
There is currently a problem with the JScript.NET compiler that gives a type mismatch error when compiling with an
HttpCookie object. For this reason the variable should be defined as Object to avoid this checking:
var cookie : Object = new HttpCookie(string);
or
var cookie : Object = new HttpCookie(string1, string2);
Here are the most relevant properties of HttpCookie:
cookie.Expires
The Expires property indicates the expiration date and time of the cookie, as a .NET DateType value (a bit different
than the JScript .NET Date object. Consult a .NET reference for more details.) After this expiration date and time, the
cookie will not be sent with the request, so you can not retrieve it anymore.
cookie.Name
Name indicates the name of the cookie.
cookie.Path
Cookies are specific to the site they originate from, so client browsers only send cookies to the DNS domain from
which they were created – i.e. a www.microsoft.com cookie can not be picked up by survey.confirmit.com. But you
can set a cookie to indicate the directory path on the domain that should receive it using the Path property. Using a
Path of "/" indicates that all directory paths on the server should have access to the cookie.
cookie.Value
The Value property indicates the value for the cookie.
The majority of cookies are used as a single name and value. However, a cookie can have more than one value. The
Values property allows you to set several values and also retrieve them again as a NameValueCollection:
cookie.Values
Here is an example on how to set a cookie:
var myCookie : Object = new HttpCookie("LastVisit");
var now : DateTime = DateTime.Now; //current time
- 232 -
Forsta Confidential Forsta v2022 Scripting Manual
- 233 -
Forsta v2022 Scripting Manual Forsta Confidential
• Report level - at the Report Level you can define your Permission script and implement common functions
available in a Codelibrary script.
• Page level - at the Page level you can add a script that runs once the report page is submitted. This script is
primarily used to validate values and combinations of values in input controls on the page. You can also use
scripting to hide a page from, for example, a particular role.
• Parameters - parameters have domain scripts, mask scripts and filter summary scripts.
• Visual Components - all visual components have a Hide expression. Additionally, component definitions for
the following components can be changed dynamically using a render script:
o Tables
o Charts
o Gauges
o Verbatim Tables
o Texts
o Hit Lists
o Admin menu
o Admin menu-like options in navigator
• Filters - filter expressions can be built dynamically from a script by adding Filter Scripts within the Filter
Toolbox.
- 234 -
Forsta Confidential Forsta v2022 Scripting Manual
Performance of affected tables can however be significantly improved. It is possible to explicitly enable caching for
scripted tables by adding the following code to the table script:
table.Caching.Enabled = true;
table.Caching.CacheKey = "X"; //can use any string value
This code will function for most scripted tables. The table cache will then take into account any context that may affect
the table, for example filters, report base, parameters and benchmark, and will cache different versions of the table for
every variation of these. So even if the script modifies these properties, caching can still be enabled.
The table.Caching.CacheKey property can be used if you want to explicitly control the cache criteria for a table.
This might be useful if the table is likely to vary by factors other than the properties mentioned above. Note that this
property is not optional, so it must be set to a string value even when it is not used. The same value can be used for
all tables.
To check whether caching will function for a table, enable caching and verify that the table dynamics (for example
report base, filters, drilldowns etc.) still function correctly in View mode.
Important
Caching should be used whenever possible as it will improve performance and take load off the system.
17.3.2. Methods
report.DataSource - provides access to the project(s) defined in the Report’s data source. The input parameter is the
data source nodeid(s).
confirmit.GetProject - provides access to a project by using the Project Id as input to the GetProject method.
confirmit.GetDBDesignerSchema - by using the schemaid as input to the GetDBDesignerSchema you can access
information in Database Designer tables. The content of Database Designer tables can be used to mask or populate
dynamic lists, or control access to various components of your report.
17.3.3. Guidelines
The parameter type Project in Reportal allows you to use projects that are not in the Reportal data source . This may
be useful if you have a portal that is used for new projects that are added on a regular basis. In this case there are
three things you must do:
1. Add projects to the domain of a project parameter from the parameter domain script.
2. Grant users access to "your" (report designer's) projects.
3. Explicitly grant access to projects from the report permission script.
When granting users access to your projects, it is important that sufficient access measures are included in the
permission script to avoid unintentional access to variables in the projects that are available from the code.
- 235 -
Forsta v2022 Scripting Manual Forsta Confidential
To set this up, you must first create a resource survey which will hold the question categories. Proceed as follows:
1. Create a project in Professional Authoring, and insert a single question type which can be called Categories.
2. Enter the different categories in the Answers tab.
When the resource survey is in place, you can define in your projects which category the questions belong to.
3. Under Question Properties for your Grid, Multi or Single question, you have a Question Category field. Enter
into this field the code of the Category to which the question is to belong. Note that if a question is to belong to
several categories, you must enter the codes separated by semi-colons. Ensure there are no spaces between
the categories and semi-colons.
- 236 -
Forsta Confidential Forsta v2022 Scripting Manual
When all questions have been categorized in the survey, the report can be setup.
4. Create a parameter in the Report toolbox, and name it for example p_category.
6. Right-click on the p_category element and select Script. Enter a customized script based on the following:
- 237 -
Forsta v2022 Scripting Manual Forsta Confidential
The GetProject method, will take in as a parameter either the data source name (which is named
resource_survey in the example), or the project id. The GetQElementsGroupedByCategory method will take in
as parameters the defined resource project, the question id of the categories question. The third parameter is
a Boolean, where you can select if the Grid questions included in a parameter should be collapsed or
expanded.
When the Parameter is in place, it must be included in a List element. The List element can be included on a
Query report page where the report viewer can select a report query.
8. Right-click on the List object, and select Properties, then set up the properties as required.
- 238 -
Forsta Confidential Forsta v2022 Scripting Manual
Note: The only place this role can be used is within Reportal scripts, by calling the user.HasRole method.
Description:
In this script you can write your own classes. These classes will typically be used as follows:
• When you have some common logic that should be used from several of the other scripts in the report.
• When the logic in a hide script is too complex to be expressed in an expression, you can implement this logic
in a common class and just call this method from the hide script.
If you want to use any of the objects available in other scripts, you must pass them as parameters to the
code library script.
To add a new script, in the Report toolbox right-click on the Codelibrary Script folder node and select
Add Codelibrary Script.
Example - Codelibrary:
class MyLib
{
__function MultiplyBy100(value : Decimal) : Decimal
__{
- 239 -
Forsta v2022 Scripting Manual Forsta Confidential
All Codelibrary scripts will be stored in the Codelibrary Script folder node in the Report toolbox.
Description:
This script is always called first for each page in the report and before exporting any object to MS Office or other
format for that report.
Even though you for example mask content of a parameter used in a dropdown to limit the user’s access to specific
values, you should also write a permission script taking care of the permission control, for the following reasons:
• Even though input controls are masked, hostile users may try to hack the report using a tool to post other
values to the input controls.
• If a report user for example has access to a specific parameter value on a certain point of time, he can save a
page with the given value to one of his private folders (Viewer Presentation component). As report designer,
you may want to revoke this access at some point of time. If so, the permission script will deny this user
access to the previously saved page.
In some cases you may want to design a report using projects that are not in the report data source. This may be the
case if you are continuously making new projects available to a report and do not want to modify the report and re-
publish it each time. Two steps are required to achieve this:
1. Go to the Viewer Project Permission page and grant access to projects outside data source.
2. Explicitly grant access to required projects in this script.
If you like to initialize or change parameter values based on other parameter values, this can also be done in this
script. Alternatively use the page script for this. These two scripts are the only scripts where you are allowed to
change parameter values.
- 240 -
Forsta Confidential Forsta v2022 Scripting Manual
1. Right-click on the report page in the Report toolbox and select Script from the drop-down menu.
The Page Script page opens.
- 241 -
Forsta v2022 Scripting Manual Forsta Confidential
2. Type the required script into the appropriate field, compile to test it, and save.
Note: All visual components on a page that have Hide scripts also have a Hide script in the Report Master.
Description:
Some pages that you design in Reportal may sometimes have several input controls. Sometimes, it may be
required to validate the combination of values in these controls. That should be done from this script.
Add all validation errors into the validation error collection in the pageContext object. Then use these values
from one or more Text controls to output these messages.
If the validation error collection has any items, Reportal will stop any navigation away from this page.
- 242 -
Forsta Confidential Forsta v2022 Scripting Manual
if(page.IsSubmit)
{
if(state.Parameters.IsNull("p_date_1")||state.Parameters.IsNull("p_date_2")){
this.pageContext.ValidationErrors.Add("Please fill both dates");}
else{var d1 : DateTime = state.Parameters.GetDate("p_date_1");
var d2 : DateTime = state.Parameters.GetDate("p_date_2");
if(d2 < d1)
{
this.pageContext.ValidationErrors.Add("End date should after start date");
}
}
}
Note: All visual components on a page that have Hide scripts also have a Hide script in the Report Master.
A possible scenario could be that you wish to selectively hide a report page based on the viewer's role. Note that you
set the viewer's role in a text field under Enduser Permissions - refer to the separate Reportal User Guide for further
details.
For this example assume that you have a number of end users. Some have the role of "Manager", while the others
have the role of "Consultant". Assume you have created a page that you wish to be accessible only to those with the
Manager role and you want to hide it from the end users with the Consultant role.
1. Right-click on the page in the Report toolbox and select Script from the drop-down menu.
The Page Script page opens, with the Hide Script field towards the top.
- 243 -
Forsta v2022 Scripting Manual Forsta Confidential
For the managers this script will evaluate to FALSE, so they will be able to see the page. However for the
consultants it will evaluate to TRUE, so the page will be hidden.
• Domain script
• Mask script
• Filter Summary script
Description:
Script used to build up the domain for a parameter. Without scripting, the domains for parameters are loaded
different ways depending on parameter type:
Projects - Connect the parameter to a question in a survey containing the project IDs that you want to load.
Double-click the parameter to open the page where you can connect the project to a question.
Questionnaire Elements - Manually build a hierarchical structure of questionnaire elements from the parameter
designer page (double-click parameter to get there).
Segments - Do it the same way as for questionnaire element, except that you drag segments into the tree
structure.
String Response - Connect parameter to a question the same way as for the project parameters. This makes the
domain implicitly load the answer list of that question.
If you use a domain script for a parameter, you override the default way of loading the domain. You have to do this
loading explicitly from within the script.
The advantage is that you can then load the domain differently, for example depending who the user is and what
other selections the user has made for other parameters. Typically, you can do this based on the user’s role or
some other information from a database designer table relating user’s to elements in lists.
Projects Example:
To tie one or more projects to a report, include a parameter to your report.
1. Under parameter properties, select Type Project.
2. Right-click on the parameter, and select Script.
3. To include projects to your report, add the following script:
var p : Project = this.confirmit.GetProject('pxxxxxxx');
parameter.Items.AddProject(p);
p = this.confirmit.GetProject('pxxxxxxx');
parameter.Items.AddProject(p);
4. In the GetProject method, include the id of your project.
5. To use this parameter, include a List element in your report.
6. Drag & drop the Questionnaire Elements Example project parameter.
- 244 -
Forsta Confidential Forsta v2022 Scripting Manual
The Questionnaire Elements can be used to include questions from a project into a drop-down menu. If you
have several projects in your report, you can script which questions to display depending on the project
selected in the project parameter (p_project).
7. Create a new parameter and rename it for example p_questions.
8. Right-click on it and select Script, then enter the following code:
if(state.Parameters.IsNull("p_project"))
return;
//Checks to see if a project has been seleced. If not, nothing is
returned.
Description:
For these types of parameters, you can add a mask script to mask the parameter domain for example based on other
selections. This script is typically used when the original domain can be loaded the default way, but the list of values should
be masked in some way.
You can choose whether to use inclusive or exclusive masks, i.e. whether the keys you add to the mask are
those that should be included in or excluded from the domain.
Mask script only applies to project, segment questionnaire element and string response parameter types.
- 245 -
Forsta v2022 Scripting Manual Forsta Confidential
Description:
For some parameters it will make sense not to have one line in filter summary for each parameter. For example, if you use
one parameter to choose which question to filter by, and another to select the filter values.
In these cases you can choose to hide one of the parameters from the filter summary and customize your own label for the
other one to have the filter on one line.
Description:
- 246 -
Forsta Confidential Forsta v2022 Scripting Manual
A typical Hide expression could for example check whether or not a parameter is null. If more complex logic is required,
consider using a script library function to implement this logic.
Note: All visual components on a page that have Hide scripts also have a Hide script in the Report Master.
Description:
Use this script to dynamically add, remove or change headers for aggregated tables. If a table already has a banner or a
parameter header, this script is called after the banner header is substituted with the header from within the banner and the
parameter headers are substituted with a header for the current value for that parameter.
- 247 -
Forsta v2022 Scripting Manual Forsta Confidential
Note: If you add a script to a table, caching is disabled for that table (see Caching of Tables on page 234 for
more information).
Description:
Most typical use of this script would be to dynamically set the questionnaire element of the table based on a parameter, but
you can also change other properties of the verbatim table.
Description:
One way of using charts scripts is to allow the report user to decide dynamically the chart type and set the chart type based
on a parameter in a script.
If you set up a report in which the user can choose which question is to be used in tables and possibly also add one or more
questions to the column headers, you may have to implement some logic regarding the parts of a table that are to be
included in the chart.
- 248 -
Forsta Confidential Forsta v2022 Scripting Manual
if(!this.state.Parameters.IsNull("p_chart_type"))
{
var ct : String = this.state.Parameters.GetString("p_chart_type");
switch(ct)
{
case "pie":
chart.Series.SeriesDefault.ChartType = ChartTypes.Pie;
chart.SeriesInRows = true;
break;
case "column":
chart.Series.SeriesDefault.ChartType = ChartTypes.Column;
break;
case "bar":
chart.Series.SeriesDefault.ChartType = ChartTypes.Bar; break;
}
}
Description:
In this script you can add, remove or change exactly the same values as you can modify in the gauge style designer and
gauge designer.
- 249 -
Forsta v2022 Scripting Manual Forsta Confidential
Description:
In this script you can add, remove or change columns of the Hit List, and you can change the properties of the Hit List itself.
Description:
If a Text component has a script, any text set in the property sheet of the component will be overwritten. If your report is
multilingual, you must also check the current language of the report to add the proper texts. One workaround for this may
be to add your dynamic texts to an answer list in a multilingual survey and get the texts by using the project.GetQuestion()
and question.GetAnswer methods.
- 250 -
Forsta Confidential Forsta v2022 Scripting Manual
Description:
Build your filter expression dynamically based on parameter values. Expression syntax is the same as for
regular filter expressions.
17.5. Validation
To avoid publishing reports that contain errors, Reportal has built-in features to verify that no scripts contain syntax
errors.
On preview and compilation of a report, if script errors are found, an error frame will appear showing a list of the
errors. The list contains links that lead to the page where the error is located. There is also a Debugging tab in the
frame which will contain a list of any debugging errors found during preview.
1. To access the Validation functionality without publishing the report, go to the Report > Quality Control >
Validate Report menu command or enter an element containing a script and choose Compile from the menu.
Reportal will start to run through the script(s) checking the code. A new pane opens in the lower-right part of
the window, displaying the message “Please wait, loading list…”. Once the checking process is finished, any
errors discovered will be displayed in the pane.
The Question ID column displays the question ID or the script ID where the error is located. The Error column
provides a short summary of the error type.
2. Click the error link to open the erroneous script, in the frame above the error pane.
Any errors are stored from when a report is published to the next time it is published, and from preview to
preview. This applies to both Runtime and Validation errors.
You can at any time view a list of any errors that may have been discovered. Go to the Report > Quality Control
menu command and select Validation Errors, Runtime Errors or Debug Errors as appropriate. Note that these are
three tabs on the same page, so you can easily switch from one to the other.
- 251 -
Forsta v2022 Scripting Manual Forsta Confidential
Typical syntax errors that may be found using the script checker are referencing undeclared variables and functions,
brackets that do not match - [ ], { } or ( ) - and similar.
The errors found will be listed at the bottom of the screen, and by clicking each error you can open the script node,
question or condition containing the error.
- 252 -
Forsta Confidential Forsta v2022 Scripting Manual
"Quick Test" compiles the survey code and runs it locally on your PC without writing data back to a database. Data is
just kept in the current session. To recompile after making changes, choose the "with rebuild" option. "New
respondent" removes the data kept in the session so that you will restart on a blank survey. Quick test is perfect to
use when debugging scripts because the fact that it is does not generate a database makes it fast. This means you
can make small changes to a script and test them immediately with Quick Test (with rebuild).
If you need the test responses to be stored in a database, you can launch the survey in test mode and run the test
interview. Refer to the separate Professional Authoring user guide for further details.
The list of errors from the random data generator is clickable, and clicking on the description will open the script,
question or info where the error appeared.
- 253 -
Forsta v2022 Scripting Manual Forsta Confidential
In the example above, the problem is that the input to the Math.max method is not a list of numbers. In the code
above that method returns NaN (not a number), which makes the script fail when attempting to set the question max,
which has the numeric property. A better solution would be to use the Forsta Max function (see Max and Min on page
77 for more information), which automatically converts the values to numbers before finding the maximum.
To help debugging you can use the results tab on the questions to see top line results for each question. It is also
possible to filter these results so that you see the results only for those that got a particular error by clicking the filter
icon in the rightmost column. You can also click the link in the "Test" column to access the first interview that
experienced the error.
18.1.4.1. Response.Write
It can sometimes be difficult to find out why a script is failing. In these cases it can help to use the
Response.Write() method to output some variables to the screen. For example, in the script above which failed
when trying to set the max question, we could comment out the last line and instead output the max variable to
screen:
var max = Math.max(f("q4").values());
Response.Write("Max="+max);
//f("max").set(max);
The text from the Response.Write call will appear at the top of the page before any interview HTML. The result
from the script above will look something like this:
If an error appears inside of a loop statement, it often helps to use Response.Write to help identify in which iteration
the script fails:
for(var i : int = 0; i<codes.length; i++)
{
Response.Write("i = "+i+"<br>");
< ... >
}
Other tricks to simplify debugging is to use /* and */ to comment out part of the code to help identify exactly where
the error occurs. This can be done as a "binary search": First you comment out ½ of the code in a script. If the error
still occurs, you know that it is in the other half. Then you can comment out half of that section – and so on.
It can also be very helpful to use Top line reporting or the "results" tab on a question, the "Edit" functionality under
"Survey Data" or doing a data export of the responses with "error" status to look into what answers actually are stored
in the question(s) involved in the script code.
- 254 -
Forsta Confidential Forsta v2022 Scripting Manual
• Test - new respondent - this mode clears any answers you may already have added to the survey in previous
tests, and runs the survey.
• Test - same respondent - if you have already run a test and then perhaps made some changes to a question,
using this test mode means any answers you have already added to the survey are remembered. You will then
be able to move quickly through the survey to the question you wish to view, without having to add all the
answers again.
• Generate external test - an externally accessible test link to the survey is generated, and you can then make
this link available to people who do not have a Forsta User login.
• View warnings and errors - in the event errors are found when the test is run, these will be listed on the
Warnings and Errors page until the errors are rectified. Select this option to view the list, and click on an error
in the list to go to the question containing the error.
When you select Test - new respondent or Test - same respondent, the survey loads and opens at the first
question in the main area of the screen as the respondent would see it. Note that the Survey pane changes color to
pale blue to indicate you are in the Test mode.
Note also that the system will remember which test mode you last used for this survey. If you wish to use the other
mode then you must change the mode using the drop-down menu.
Additional Options
A number of additional options are available while testing - in the Test area toolbar click the Options icon to open a
drop-down menu. Here you can select whether you wish to view background questions, panel questions and/or
hidden questions while you are testing. Note that these settings only apply whilst you are in the test mode; they will
not have any effect on the production survey. Your selections will be remembered and applied whenever this survey is
in Test mode.
For further information, refer to the separate Survey Designer user guide.
- 255 -
Forsta v2022 Scripting Manual Forsta Confidential
19.1. Comments
It is recommended to make extensive use of comments in your scripts. They will help you and others to more quickly
understand the way your code works and how to use it (see Comments on page 15 for more information).
• variable names and names of methods and properties should start with a lowercase letter in the first word. The
next words should open with an uppercase letter. Examples: gridCodes, availableCodes, randomNumber,
indexOuterLoop.
• function names and names of objects should start with an uppercase in the first word, and have uppercase
letters in the beginning of all subsequent words. Examples: CopyMulti, SelectItems, CalculateAverage.
- 256 -
Forsta Confidential Forsta v2022 Scripting Manual
if(condition)
{
<statement1>;
}
so you may find it convenient to drop the curly brackets. But you may soon need to add another statement. If you add
it like this:
if(condition)
<statement1>;
<statement2>;
or
if(condition)
<statement1>; <statement2>;
it will be equivalent to
if(condition)
{
<statement1>;
}
<statement2>;
This will be very different from
if(condition)
{
<statement1>;
<statement2>;
}
- 257 -
Forsta v2022 Scripting Manual Forsta Confidential
The first code will be a bit more efficient than the latter, because you do not have to store values in the variables
randomNumber and randomIndex. However, because it will be much easier to understand what happens in the last
one, that approach is recommended.
To increase readability, use temporary variables and do the calculations step by step.
- 258 -
Forsta Confidential Forsta v2022 Scripting Manual
Note: For Offline Apps (CAPI, AskMe, the JavaScript engine MUST be used.
Note: Try-catch blocks must not be used in JavaScripts as errors will then be created.
SurveyArrayList no
f('q1').values().toString() == "1, 2" f('q1').values().toString() == "System.Object[]" longer exists, so
^f('q1').values()^ returns "1,2" ^f('q1').values()^ returns "System.Object[]" standard .NET array is
used. String
representation of
standard .NET types
cannot be changed.
item() instead of .NET
f('q1')['1'] f('q1').item(1) indexer [].
f('q1')('1') f('q1').item(1)
f('q1').get_Item('1') f('q1').item(1)
Request.Form['q1'] Request.Form.item('q1')
Request.QueryString["test"] Request.QueryString.item('test')
UserParameters[paramName] UserParameters.item(paramName)
No strict types
var o : Date = new Date() var o = new Date() declaration.
function ImagenesURL():String { function ImagenesURL() { return '' }
return '' }
- 259 -
Forsta v2022 Scripting Manual Forsta Confidential
Differences between Jscript.Net code and JavaScript code for Offline Mobile Apps (CAPI, AskMe):
Note: Any methods and properties not listed here are the same for both scripts.
UserParameters[paramName] UserParameters.item(paramName)
SetPanelistCredit(Int32 credit, String comment, String SetPanelistCreditBySectionId(Int32 credit, String comment,
sectionId) String sectionId)
SetPanelistCredit(Int32 credit, String comment, Int32 SetPanelistCreditByPanelistId(Int32 credit, String comment,
panelistId) Int32 panelistId)
SetPanelistCreditWithCustomVariables(Int32 credit, SetPanelistCreditWithCustomVariablesBySectionId(Int32
String comment, String sectionId, String[] fieldNames, credit, String comment, String sectionId, String[] fieldNames,
String[] fieldValues) String[] fieldValues)
SetPanelistCreditWithCustomVariables(Int32 credit, SetPanelistCreditWithCustomVariablesByPanelistId(Int32
String comment, Int32 panelistId, String[] fieldNames, credit, String comment, Int32 panelistId, String[] fieldNames,
String[] fieldValues) String[] fieldValues)
N/A Cookies
N/A CreateCookieObject(String name, String value)
- 260 -
Forsta Confidential Forsta v2022 Scripting Manual
20.2.2. ExprObj
Difference table:
20.2.3. Set
Difference table:
20.2.4. Request
Note: Request is only supported for online interviewing; it is not available in off-line interviewing.
- 261 -
Forsta v2022 Scripting Manual Forsta Confidential
N/A
Void Abort()
Byte[] BinaryRead(Int32 count)
String[] AcceptTypes
String AnonymousID
String ApplicationPath
String AppRelativeCurrentExecutionFilePath
HttpClientCertificate ClientCertificate
Encoding ContentEncoding
HttpCookieCollection Cookies
String CurrentExecutionFilePath
String CurrentExecutionFilePathExtension
String FilePath
HttpFileCollection Files
Stream Filter
ChannelBinding HttpChannelBinding
String HttpMethod
Stream InputStream
Boolean IsAuthenticated
Boolean IsLocal
Boolean IsSecureConnection
String Item
WindowsIdentity LogonUserIdentity
String PathInfo
String PhysicalApplicationPath
String RawUrl ReadEntityBodyMode
ReadEntityBodyMode
RequestContext RequestContext
String RequestType
CancellationToken TimedOutToken
Int32 TotalBytes
UnvalidatedRequestValues Unvalidated
Uri UrlReferrer
String UserHostAddress
String UserHostName
String[] UserLanguages
Stream GetBufferedInputStream()
Stream GetBufferlessInputStream()
Stream GetBufferlessInputStream(Boolean
disableMaxRequestLength)
Void InsertEntityBody()
Void InsertEntityBody(Byte[] buffer, Int32 offset, Int32 count)
Int32[] MapImageCoordinates(String imageFieldName)
String MapPath(String virtualPath)
String MapPath(String virtualPath, String baseVirtualDir, Boolean
allowCrossAppMapping)
Double[] MapRawImageCoordinates(String imageFieldName)
Void SaveAs(String filename, Boolean includeHeaders)
String ToString()
20.2.5. Response
Note: Response is only supported for online interviewing; it is not available in off-line interviewing.
- 262 -
Forsta Confidential Forsta v2022 Scripting Manual
- 263 -
Forsta v2022 Scripting Manual Forsta Confidential
N/A
Void AddCacheDependency(CacheDependency[] dependencies)
Void AddCacheItemDependencies(ArrayList cacheKeys)
Void AddCacheItemDependencies(String[] cacheKeys)
Void AddCacheItemDependency(String cacheKey)
Void AddFileDependencies(ArrayList filenames)
Void AddFileDependencies(String[] filenames)
Void AddFileDependency(String filename)
Void AddHeader(String name, String value)
ISubscriptionToken AddOnSendingHeaders(Action`1 callback)
Void AppendCookie(HttpCookie cookie)
Void AppendHeader(String name, String value)
Void AppendToLog(String param)
String ApplyAppPathModifier(String virtualPath)
IAsyncResult BeginFlush(AsyncCallback callback, Object state)
Void BinaryWrite(Byte[] buffer)
Void ClearContent()
Void ClearHeaders()
Void DisableKernelCache()
Void DisableUserCache()
Void End()
Void EndFlush(IAsyncResult asyncResult)
Void Flush()
Boolean Buffer
Boolean BufferOutput
HttpCachePolicy Cache
String CacheControl
String Charset
CancellationToken ClientDisconnectedToken
Encoding ContentEncoding
String ContentType
HttpCookieCollection Cookies
DateTime ExpiresAbsolute
Stream Filter
Encoding HeaderEncoding
Boolean HeadersWritten
Boolean IsClientConnected
Boolean IsRequestBeingRedirected
TextWriter Output
tream OutputStream
String RedirectLocation
Int32 StatusCode
String StatusDescription
Int32 SubStatusCode
Boolean SupportsAsyncFlush
Boolean SuppressContent
Boolean SuppressDefaultCacheControlHeader
Boolean SuppressFormsAuthenticationRedirect
Boolean TrySkipIisCustomErrors
Void Pics(String value)
Void RedirectPermanent(String url)
Void RedirectPermanent(String url, Boolean endResponse)
Void RedirectToRoute(Object routeValues)
Void RedirectToRoute(String routeName)
Void RedirectToRoute(RouteValueDictionary routeValues)
Void RedirectToRoute(String routeName, Object routeValues)
Void RedirectToRoute(String routeName, RouteValueDictionary
routeValues)
Void RedirectToRoutePermanent(Object routeValues)
Void RedirectToRoutePermanent(String routeName)
Void RedirectToRoutePermanent(RouteValueDictionary
routeValues)
- 264 -
Forsta Confidential Forsta v2022 Scripting Manual
20.2.6. Server
- 265 -
Forsta v2022 Scripting Manual Forsta Confidential
N/A
Void ClearError()
Object CreateObject(String progID)
Object CreateObject(Type type)
Object CreateObjectFromClsid(String clsid)
Void Execute(String path)
Void Execute(String path, TextWriter writer)
Void Execute(String path, Boolean preserveForm)
Void Execute(String path, TextWriter writer, Boolean preserveForm)
Void Execute(IHttpHandler handler, TextWriter writer, Boolean preserveForm)
String MachineName
Int32 ScriptTimeout
Exception GetLastError()
Void HtmlDecode(String s, TextWriter output)
Void HtmlEncode(String s, TextWriter output)
String MapPath(String path)
String ToString() Void Transfer(String path)
Void Transfer(String path, Boolean preserveForm)
Void Transfer(IHttpHandler handler, Boolean preserveForm)
Void TransferRequest(String path)
Void TransferRequest(String path, Boolean preserveForm)
Void TransferRequest(String path, Boolean preserveForm, String method,
NameValueCollection headers)
Void TransferRequest(String path, Boolean preserveForm, String method,
NameValueCollection headers, Boolean preserveUser)
Void UrlDecode(String s, TextWriter output)
Void UrlEncode(String s, TextWriter output)
String UrlPathEncode(String s)
Byte[] UrlTokenDecode(String input)
String UrlTokenEncode(Byte[] input)
20.2.7. NameValueCollection
- 266 -
Forsta Confidential Forsta v2022 Scripting Manual
20.2.8. Browser
Note: Browser is only supported for online interviewing; it is not available in off-line interviewing.
- 267 -
Forsta v2022 Scripting Manual Forsta Confidential
- 268 -
Forsta Confidential Forsta v2022 Scripting Manual
Boolean RequiresHtmlAdaptiveErrorReporting
Boolean RequiresLeadingPageBreak
Boolean RequiresNoBreakInFormatting
Boolean RequiresOutputOptimization
Boolean RequiresPhoneNumbersAsPlainText
Boolean RequiresSpecialViewStateEncoding
Boolean RequiresUniqueFilePathSuffix
Boolean RequiresUniqueHtmlCheckboxNames
Boolean RequiresUniqueHtmlInputNames
Boolean RequiresUrlEncodedPostfieldValues
Int32 ScreenBitDepth
Int32 ScreenCharactersHeight
Int32 ScreenCharactersWidth
Int32 ScreenPixelsHeight
Int32 ScreenPixelsWidth
Boolean SupportsAccesskeyAttribute
Boolean SupportsBodyColor
Boolean SupportsBold
Boolean SupportsCacheControlMetaTag
Boolean SupportsCallback
Boolean SupportsCss
Boolean SupportsDivAlign
Boolean SupportsDivNoWrap
Boolean SupportsEmptyStringInCookieValue
Boolean SupportsFontColor
Boolean SupportsFontName
Boolean SupportsFontSize
Boolean SupportsImageSubmit
Boolean SupportsIModeSymbols
Boolean SupportsInputIStyle
Boolean SupportsInputMode
Boolean SupportsItalic
Boolean SupportsJPhoneMultiMediaAttributes
Boolean SupportsJPhoneSymbols
Boolean SupportsQueryStringInFormAction
Boolean SupportsRedirectWithCookie
Boolean SupportsSelectMultiple
Boolean SupportsUncheck
Boolean SupportsXmlHttp
Type TagWriter
Boolean UseOptimizedCacheKey
Version W3CDomVersion
Boolean Win16
Boolean Win32
Version[] GetClrVersions()
String ToString()
20.2.9. JavaScriptScriptingExtensionPoint
- 269 -
Forsta v2022 Scripting Manual Forsta Confidential
20.2.10. JavaScriptCallResultCollection
20.2.11. Cookies
Note: This is a replacement for Request.Cookies. Note also that Cookies is only supported for online
interviewing; it is not available in off-line interviewing.
- 270 -
Forsta Confidential Forsta v2022 Scripting Manual
N/A
Void CopyTo(Array dest, Int32 index)
Void Clear()
this[Int32 index]
KeysCollection Keys
IEnumerator GetEnumerator()
String GetKey(Int32 index)
String ToString()
* - You can get a cookie with the Cookies.Get method or create a new cookie with CreateCookieObject method. Note
that in either case, on completion you must save the changes with the Cookies.Save method.
20.2.12. Cookie
Note: This is a replacement for Request.Cookies. Note also that Cookie is only supported for online
interviewing; it is not available in off-line interviewing.
- 271 -
Forsta v2022 Scripting Manual Forsta Confidential
1,2,6,7,9,10,12
- 272 -
Forsta Confidential Forsta v2022 Scripting Manual
11
2,4,5,10,11
Exercise 7:
- 273 -
Forsta v2022 Scripting Manual Forsta Confidential
if(!d)
{
RaiseError();
SetQuestionErrorMessage(LangIDs.en,"Invalid date. Please correct using
the format MM/DD YYYY");
}
else
{
var dt = new Date();
dt.setFullYear(d.year,d.month-1,d.day);
var current = new Date();
if(dt.valueOf() < current.valueOf())
{
RaiseError();
SetQuestionErrorMessage(LangIDs.en,"Please enter a date after the
current date.");
}
else if(dt.getDay() != 1)
{ RaiseError();
SetQuestionErrorMessage(LangIDs.en,f("date4")+" is not a Monday.
Please register for Mondays only.");
}
}
Exercise 8:
var num : String = f("phone").get();
var re = /^\d{3} \d{3} \d{4}$/;
if(!re.test(num))
{
RaiseError();
SetQuestionErrorMessage(LangIDs.en,"Please provide your phone number on
the format xxx xxx xxxx");
}
Exercise 9:
var zipcode : String = f("zipcode").get();
var re = /^\d{5}$/;
if(zipcode.search(re) == -1)
{
RaiseError();
SetQuestionErrorMessage(LangIDs.en,"Please provide a valid zip code
(digits only).");
}
- 274 -
Forsta Confidential Forsta v2022 Scripting Manual
Important
Custom languages that are added after the initial release of Forsta are assigned a Language code number
automatically, based on the order in which the languages are added. Custom languages may therefore have
different language IDs for each installation of Forsta (On-Premise, SaaS Euro, SaaS US, SaaS AU). Therefore,
be aware that if you intend to export/import surveys between the different environments (On-
Premise/Euro/US/AU) and you are using custom languages, you should check the relevant language codes
for the sites and edit the XML export files as appropriate.
For each installation; go to the Home > Help > Language Overview menu command to view a list of the
languages, with their applicable codes, available on that server.
54 Afrikaans af
28 Albanian sq
1 Arabic ar
- 275 -
Forsta v2022 Scripting Manual Forsta Confidential
43 Armenian hy
77 Assamese as
44 Azeri az
45 Basque eu
35 Belarusian be
69 Bengali bn
517 Bosnian bo
2 Bulgarian bg
3 Catalan ca
4 Chinese zh
518 Croatian hr
- 276 -
Forsta Confidential Forsta v2022 Scripting Manual
5 Czech cs
6 Danish da
19 Dutch nl
9 English en
37 Estonian et
56 Faeroese fo
41 Farsi fa
- 277 -
Forsta v2022 Scripting Manual Forsta Confidential
11 Finnish fi
12 French fr
514 Gaelic gd
55 Georgian ka
7 German de
8 Greek el
513 Greenlandic gl
71 Gujarati gu
13 Hebrew he
57 Hindi hi
14 Hungarian hu
15 Icelandic is
33 Indonesian id
- 278 -
Forsta Confidential Forsta v2022 Scripting Manual
16 Italian it
17 Japanese ja
75 Kannada kn
96 Kashmiri ks
63 Kazak kk
520 Khmer kh
87 Konkani ki
18 Korean ko
38 Latvian lv
39 Lithuanian lt
47 Macedonian mk
62 Malay ms
- 279 -
Forsta v2022 Scripting Manual Forsta Confidential
76 Malayalam ml
88 Manipuri ma
78 Marathi mr
97 Nepali ne
20 Norwegian no
72 Oriya or
516 Pashto ps
21 Polish pl
22 Portuguese pt
70 Punjabi pa
24 Romanian ro
25 Russian ru
79 Sanskrit sa
26 Serbian / Croatian sr
- 280 -
Forsta Confidential Forsta v2022 Scripting Manual
89 Sindhi sd
519 Sinhalese si
27 Slovak sk
36 Slovenian sl
10 Spanish es
- 281 -
Forsta v2022 Scripting Manual Forsta Confidential
65 Swahili sw
29 Swedish sv
73 Tamil ta
68 Tatar tt
74 Telugu te
30 Thai th
31 Turkish tr
34 Ukrainian uk
32 Urdu ur
67 Uzbek uz
42 Vietnamese vi
512 Welsh cy
521 Zulu zu
- 282 -
Forsta Confidential Forsta v2022 Scripting Manual
APPENDIX D: Codepage
- 283 -
Forsta v2022 Scripting Manual Forsta Confidential
Korean 949
- 284 -
Forsta Confidential Forsta v2022 Scripting Manual
- 285 -
Forsta v2022 Scripting Manual Forsta Confidential
37. Retrieving and Listing the last 10 Panelist Credits Transactions inside a Survey
38. Retrieving and Listing the last 10 Panelist Credits Transactions inside a Survey, including custom variables
39. Inserting a new Panelist in a Panel
40. Update Panel Variables in a Panel
41. Retrieving Data for a Panelist in a Panel
42. Update Survey History Panel Variables in a Panel
43. Redirect back to Panel Portal
44. Checking that a Response in a Multi Open Text Question is an Integer
45. Validating Date Format of Open Text Date Question
46. Validating Date with Drop-downs for the Date Parts
47. Validation of Email Address Format
48. Excluding Respondents from Specific Networks
49. Send Confirmation Email at the End of a Survey
50. Invitation Email to a Different Part of the Same Survey
51. Sending a PDF to the respondent with answers from the survey
52. Redirect to Another Site Before the End Page
53. Code Masking Based on a Variable Number of Conditional Expressions
54. Returning a Calculated Value from a Function
55. Using a Variable instead of Repeated Calls on the f Function
56. Deleting the Content of any Question
57. Copying the Contents of any Form into Another
58. Filtering an Answer List by the First Characters in the Answer
59. Asking for Favorite Only when More than 1 Item is Chosen
60. Filtering an Answer List on Items Selected in Two Previous Questions
61. Filtering Answers Not Selected in a Previous Question
62. Always Including a "Don't know" Answer Alternative
63. Validating "Other, specify" in a 3D Grid
64. Using a Function to Filter an Answer List Based on the Answers on a Grid
65. Using a Hidden Multi to Filter an Answer List Based on a Grid
66. Calculating Time Spent
67. Validating that a Date with Drop-downs is within the next two Weeks
68. Finding the Weekday
69. Converting Data of Birth into Age (in number of years)
70. Rounding to a Number with Two Digits
71. Picking n Random Items from the Answers to a Multi Question
72. Randomly Assigning which Part of a Survey the Respondents Should Answer
73. Using modulus to route respondents to different parts of the questionnaire
74. Checking a User Name and Password where Username is Case Insensitive
75. On the Fly Recoding
- 286 -
Forsta Confidential Forsta v2022 Scripting Manual
- 287 -
Forsta v2022 Scripting Manual Forsta Confidential
Routing
IF var_single(1);
If f(‘var_single’)==’1’ Use in Condition Check if answer
ENDIF; Node category 1 of
single var is
switched on
IF var_single(1 | 2);
f(‘var_single’)==’1’ || f(‘var_single’)==’2’ Consider nset() and Check if answers
ENDIF; or nnset() when using 1 OR 2 are
set('1','2').inc(f('var_single')) numeric codes switched on
IF ^var_single(1);
!(f(‘var_single’)==’1’ ) or “ Check if single var
does NOT have
code 1 switched
ENDIF; f(‘var_single’)!=’1’
on
- 288 -
Forsta Confidential Forsta v2022 Scripting Manual
Run Mode IF RUN_MODE()==R$4(WEB); GetSurveyChannel == ‘Cawi’ Use in Condition node Checks if Run
(Web) Mode is Web
ENDIF;
- 289 -
Forsta v2022 Scripting Manual Forsta Confidential
While WHILE (<condition>); While (<condition>) See While in Scripting While loop – stay
manual – also see ‘Do in while loop while
While’ and ‘For’ in condition
ENDWHILE; { <statements> }
Scripting manual evaluates to True
Operators
- 290 -
Forsta Confidential Forsta v2022 Scripting Manual
Calculations
Temp TEMPORARY <temp_var>; vartemp_var : int; OR vartemp_var : int Defined in script Creates a
= value (if assigning as well) nodes, and validation temporary quantity
code. variable
- 291 -
Forsta v2022 Scripting Manual Forsta Confidential
Masking
Quotas
- 292 -
Forsta Confidential Forsta v2022 Scripting Manual
Define quota <quota_name>: LOOKUP_B These are defined in the Questionnaire Defines quota
<var_single> (150 150); Tree. Refer to the separate Survey <quota_name>
Designer user guide for further where target
information. quotas are 150 in
answer1 and 150
in answer2 from
<var_single>
Assign quotas Compute <quantity_var> f('quantity_var').set(qc('quota_name')) sets current count into Computes to
to variable Quota_Value(<quota_name>,1) question <quantity_var> the
'quantity_var'. current number of
Achieved
interviews in cell 1
of <quota_name>
Functions
- 293 -
Forsta v2022 Scripting Manual Forsta Confidential
Under 18
18 to 65 inc
66 or more
Appropriate
answer category
will be switched on
in target
depending on
value of
age_quantity
Date
functions
Misc.
- 294 -
Forsta Confidential Forsta v2022 Scripting Manual
- 295 -
Forsta v2022 Scripting Manual Forsta Confidential
Index
?
- (operator), 27 ? (regular expression syntax), 205, 208
-- (operator), 28 ? : (operator), 30
- (regular expression syntax), 206 ?! (regular expression syntax), 210
?: (regular expression syntax), 209
?= (regular expression syntax), 210
!
! (operator), 28 [
!= (operator), 29
!== (operator), 29 [] (regular expression syntax), 205, 206
# \
#, 15, 22, 27, 28, 29, 30, 35, 204, 205, 206, 207, 208, \ (regular expression syntax), 205, 210, 211
209, 210, 211, 256, 257 \\ (regular expression syntax), 205
\- (regular expression syntax), 207
\\ (string formatting character), 22
$ \' (string formatting character), 22
$ (regular expression syntax), 204, 208 \", 22
\$ (regular expression syntax), 205
\( (regular expression syntax), 205
% \) (regular expression syntax), 205
\* (regular expression syntax), 205
% (operator), 27
\. (regular expression syntax), 205
%= (operator), 30
\? (regular expression syntax), 205
\[ (regular expression syntax), 205
& \^ (regular expression syntax), 205
\{ (regular expression syntax), 205
&& (operator), 28 \| (regular expression syntax), 205
\+ (regular expression syntax), 205
( \b (regular expression syntax), 208
\B (regular expression syntax), 208
() (regular expression syntax), 204, 209 \b (string formatting character), 22
(semi colon), 35, 257 \c (regular expression syntax), 206
\d (regular expression syntax), 211
* \D (regular expression syntax), 211
\f (regular expression syntax), 206
* (operator), 27 \n (regular expression syntax), 206
* (regular expression syntax), 204, 208 \n (string formatting character), 22
*= (operator), 30 \r (regular expression syntax), 206
\r (string formatting character), 22
\s (regular expression syntax), 206
. \S (regular expression syntax), 206
. (regular expression syntax), 205 \t (regular expression syntax), 206
.any, .all and .none, 179 \t (string formatting character), 22
\u (regular expression syntax), 211
\v (regular expression syntax), 206
/ \w (regular expression syntax), 211
/ (operator), 27 \W (regular expression syntax), 211
/* */ (comment), 15 \x (regular expression syntax), 211
// (comment), 15
/= (operator), 30 ^
^ (regular expression syntax), 205, 207, 208
- 296 -
Forsta Confidential Forsta v2022 Scripting Manual
- 297 -
Forsta v2022 Scripting Manual Forsta Confidential
- 298 -
Forsta Confidential Forsta v2022 Scripting Manual
int, 20 datestring, 26
long, 20 DateType (object), 232
Number, 21 day, 26
object, 164 day (property), 188
sbyte, 20 decimal, 21
short, 20 decimal numbers, 19
string, 21 declaration (statement), 35
uint, 20 Declare variables, 2
ulong, 20 Declaring JScript Arrays, 40
ushort, 20 Declaring Typed Arrays, 39
Date, 49 decrement (operator), 28
Date (object), 181 DEF_EXCL (error template), 222
Constructors, 181 DEF_EXCL_AND (error template), 223
getDate (method), 185 DEF_EXCL_OR (error template), 223
getDay (method), 184 DEF_NEXCL (error template), 223
getFullYear (method), 183 DEF_NEXCL_AND (error template), 223
getHours (method), 185 DEF_NEXCL_OR (error template), 223
getMilliseconds (method), 186 DeleteCurrentResponse (function), 143
getMinutes (method), 185 device pixel ratio, 91
getMonth (method), 184 DeviceLanguage, 100
getSeconds (method), 186 DeviceLanguageId, 101
getTime (method), 186 DeviceLocale, 101
getTimezoneOffset (method), 187 DeviceModel, 101
getUTCDate (method), 185 DeviceName, 101
getUTCDay (method), 184 DeviceOs, 101
getUTCFullYear (method), 183 DeviceOsVersion, 101
getUTCHours (method), 185 DeviceUniqueId, 101
getUTCMilliseconds (method), 186 DICHOTOMY (property), 167
getUTCMinutes (method), 185 diff (method), 174
getUTCMonth (method), 184 Differences between JavaScript and JScript, 259
getUTCSeconds (method), 186 Digits and Word Characters, 211
getYear (method), 184 division (operator), 27
methods, 182 do while (statement), 65
parse (method), 182 Domain Scripts, 244
setDate (method), 185 domainLabels (method), 43
setFullYear (method), 183 domainValues (method), 43
setHours (method), 185 double, 21
setMilliseconds (method), 186 Dynamic Questions, 11
setMinutes (method), 185 DynamicQuestionsEnabled (function), 80
setMonth (method), 184
setSeconds (method), 186
setTime (method), 186
E
setUTCDate (method), 185 E (property), 193
setUTCFullYear (method), 183 Element of a Grid Question, 58
setUTCHours (method), 185 Element of a Multi Question, 58
setUTCMilliseconds (method), 186 Element of an Open Text List Question, 58
setUTCMinutes (method), 185 else, 36
setUTCMonth (method), 184 EnableLiveMonitoring, 123
setUTCSeconds (method), 186 equal (operator), 28
setYear (method), 184 ErrorTemplate (function), 221
toGMTString (method), 187 DEF_EXCL, 222
toLocaleString (method), 187 DEF_EXCL_AND, 223
toString (method), 187 DEF_EXCL_OR, 223
toUTCString (method), 187 DEF_NEXCL, 223
UTC (method), 182 DEF_NEXCL_AND, 223
valueOf (method), 187 DEF_NEXCL_OR, 223
DATE (property), 167 MAX_SIZE, 224
Date Conversion Methods, 187 MISSING, 222
Date Functions, 187 MISSING_AND, 222
Date Object, 181 MISSING_OR, 222
Date Question Type, 192 NUMERIC_ERRORS, 225
Date Questions, 187 NUMERIC_ERRORS_AND, 225
- 299 -
Forsta v2022 Scripting Manual Forsta Confidential
- 300 -
Forsta Confidential Forsta v2022 Scripting Manual
- 301 -
Forsta v2022 Scripting Manual Forsta Confidential
- 302 -
Forsta Confidential Forsta v2022 Scripting Manual
- 303 -
Forsta v2022 Scripting Manual Forsta Confidential
- 304 -
Forsta Confidential Forsta v2022 Scripting Manual
R S
RaiseError (function), 8 Sample Only, 143
Random, 195 sbyte, 20
random (method), 195 SCALE (error template), 226
Random Data Generator, 253 Scale masking, 11
RANGE_ERRORS (error template), 226 scale masks, 6, 171
RANGE_ERRORS_AND (error template), 226 Scale Masks, 180
RANGE_MAX (error template), 226 SCALE_ERRORS (error template), 226
RANGE_MIN (error template), 226, 227 SCALE_ERRORS_AND (error template), 226
RangeError (function), 221, 226 ScaleError (function), 221, 226
Rank and Capture Order Multis, 95 Scheduling script
Rank order tests, 220 custom script, 125
RANK_MAX (error template), 224 Screen dimension, 91
RANK_MIN (error template), 224 screen.height, 91
RankError (function), 221, 224 screen.width, 91
Redirect, 156 Script .NET Fast Mode, 1
Redirect (function), 156 Script Execution, 12
RedirectToExternalSurvey, 143 script nodes, 10
RedirectToRespondentUrl, 84 Script Types, 239
RedirectToRouterSurvey, 159 Script Validation, 251
Redo (function), 109 Scripting
Referencing the Elements, 57 Guidelines, 235
RegExp (object), 203 Where is it used, 234
Constructors, 203, 212 Scripting Concepts, 235
exec (method), 212 Scripting in Reportal, 234
- 305 -
Forsta v2022 Scripting Manual Forsta Confidential
- 306 -
Forsta Confidential Forsta v2022 Scripting Manual
- 307 -
Forsta v2022 Scripting Manual Forsta Confidential
- 308 -