<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://www.limesurvey.org/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=LimeAJ</id>
	<title>LimeSurvey Manual - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://www.limesurvey.org/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=LimeAJ"/>
	<link rel="alternate" type="text/html" href="https://www.limesurvey.org/manual/Special:Contributions/LimeAJ"/>
	<updated>2026-08-12T11:21:14Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.43.9</generator>
	<entry>
		<id>https://www.limesurvey.org/manual/index.php?title=Menu_configuration&amp;diff=117388</id>
		<title>Menu configuration</title>
		<link rel="alternate" type="text/html" href="https://www.limesurvey.org/manual/index.php?title=Menu_configuration&amp;diff=117388"/>
		<updated>2018-07-05T13:18:29Z</updated>

		<summary type="html">&lt;p&gt;LimeAJ: Minor grammar correction.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;languages /&amp;gt;&lt;br /&gt;
&amp;lt;translate&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:1--&amp;gt;&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:17--&amp;gt;&lt;br /&gt;
{{Alert|text=Under construction}}&lt;br /&gt;
&lt;br /&gt;
=General= &amp;lt;!--T:2--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:9--&amp;gt;&lt;br /&gt;
If you would like to create a new menu or add new entries to a preexisting menu, access &#039;&#039;&#039;Menu configuration&#039;&#039;&#039; from the &#039;&#039;&#039;Configuration&#039;&#039;&#039; dialog.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:18--&amp;gt;&lt;br /&gt;
&amp;lt;center&amp;gt;[[File:Menu Configuration.png]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:10--&amp;gt;&lt;br /&gt;
If you are unhappy with the existing survey menus or you wish to create a special survey menu for a certain user group, edit the default ones or create new menus. You can also add new [[Menu entries configuration#Create a menu entry|menu entries]] or [[Menu entries configuration#Edit menu entry|edit the existing ones]].&lt;br /&gt;
&lt;br /&gt;
=Survey Menu= &amp;lt;!--T:3--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:11--&amp;gt;&lt;br /&gt;
Once accessed, you can see in the Menu Configuration panel a table with all the existing survey menus.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:19--&amp;gt;&lt;br /&gt;
&amp;lt;center&amp;gt;[[File:Survey Menus.png]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:12--&amp;gt;&lt;br /&gt;
Four actions are available:&lt;br /&gt;
*[[Menu configuration#Create a menu|Create a menu]]&lt;br /&gt;
*[[Menu configuration#Edit a menu|Edit a menu]]&lt;br /&gt;
*[[Menu configuration#Delete a menu|Delete a menu]]&lt;br /&gt;
*[[Menu configuration#Reset to default values|Reset to default values]]&lt;br /&gt;
&lt;br /&gt;
==Create a menu== &amp;lt;!--T:4--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:13--&amp;gt;&lt;br /&gt;
If you would like to create a new menu, press on the green button (&#039;&#039;&#039;+ New&#039;&#039;&#039;) located in the upper left part of the window. The following window will pop-up:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:14--&amp;gt;&lt;br /&gt;
&amp;lt;center&amp;gt;[[File:Create a New Menu.png|Create a New Menu.png]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:5--&amp;gt;&lt;br /&gt;
A group of options is available:&lt;br /&gt;
*&#039;&#039;&#039;Parent&#039;&#039;&#039;: Use this option to select the parent menu of another survey menu. In this way, a survey menu will be displayed within another menu once clicked. For example, the plugin menu is a survey menu that has as parent menu the &#039;&#039;mainmenu&#039;&#039;, being displayed the bottom of it due to its &#039;&#039;&#039;order&#039;&#039;&#039;.&lt;br /&gt;
*&#039;&#039;&#039;Survey&#039;&#039;&#039;: You can choose the survey the menu will be available for. It comes automatically set up for &#039;&#039;All surveys&#039;&#039;;&lt;br /&gt;
*&#039;&#039;&#039;Ordering&#039;&#039;&#039;: If you use more menus that have the same position, ordering them would help you better organize them.&lt;br /&gt;
*&#039;&#039;&#039;Title&#039;&#039;&#039;: The tile of the menu;&lt;br /&gt;
*&#039;&#039;&#039;Description&#039;&#039;&#039;: A short summary of the entries that will be added to that menu can be added - useful for other LimeSurvey administrators that wish to later change the configuration of the survey menus;&lt;br /&gt;
*&#039;&#039;&#039;Position&#039;&#039;&#039;: Four positions are available:&lt;br /&gt;
**&#039;&#039;Sidemenu&#039;&#039; : The menu will be located on the left side of the window;&lt;br /&gt;
**&#039;&#039;Collapsed menu&#039;&#039; : A collapsed menu will display only the icons of the survey menu entries;&lt;br /&gt;
**&#039;&#039;Top bar&#039;&#039; : The menu is going to be on a bar located in the upper part of the window;&lt;br /&gt;
**&#039;&#039;Bottom bar&#039;&#039; : The menu is going to be on a bar located in the lower part of the window.&lt;br /&gt;
&lt;br /&gt;
==Edit a menu== &amp;lt;!--T:20--&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:15--&amp;gt;&lt;br /&gt;
If you would like to change the details of an already existing menu, click on the green button located in the &#039;&#039;Action&#039;&#039; column. Once done&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:21--&amp;gt;&lt;br /&gt;
&amp;lt;center&amp;gt;[[File:Edit existing survey menu.png]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Delete a menu== &amp;lt;!--T:6--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:16--&amp;gt;&lt;br /&gt;
If you want to delete a menu, click on the red trash button that corresponds to that respective menu (located in the &#039;&#039;&#039;Action&#039;&#039;&#039; column). If you click &#039;&#039;&#039;Delete now&#039;&#039;&#039;, all the menu entries of that menu will also be deleted.&lt;br /&gt;
&lt;br /&gt;
==Reset to default values== &amp;lt;!--T:22--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:23--&amp;gt;&lt;br /&gt;
In the case in which you edited the default menus and you want to return back to the default values, click on the &#039;&#039;&#039;Reset&#039;&#039;&#039; button located in the upper right part of the window. Once clicked, you will be asked to confirm the operation. Please note that all the custom menus will be lost if you decide to proceed.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:24--&amp;gt;&lt;br /&gt;
&amp;lt;center&amp;gt;[[File:Restore default survey menus.png]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:25--&amp;gt;&lt;br /&gt;
{{Alert|title=Attention|text=Please note that in order to backup your survey menus configuration, create a [[Backup entire database|LimeSurvey database backup]]. A separate option will be introduced in the near future to facilitate only the backup of the survey menus.}}&lt;br /&gt;
&lt;br /&gt;
=Examples= &amp;lt;!--T:7--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:26--&amp;gt;&lt;br /&gt;
Check the following examples to better understand how you can edit survey menus.&lt;br /&gt;
&lt;br /&gt;
== I want the default collapsed menu to become the new sidemenu == &amp;lt;!--T:27--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:28--&amp;gt;&lt;br /&gt;
The default sidemenu (located under the [[Survey settings|survey settings tab]]) is:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:29--&amp;gt;&lt;br /&gt;
&amp;lt;center&amp;gt;[[File:Default survey settings menu.png]]&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:30--&amp;gt;&lt;br /&gt;
To change it, access the menu configuration panel. Edit the &#039;&#039;mainmenu&#039;&#039; and change its position from &#039;&#039;&#039;sidemenu&#039;&#039;&#039; to &#039;&#039;&#039;collapsed menu&#039;&#039;&#039;, and the position of the &#039;&#039;quickmenumenu&#039;&#039; from &#039;&#039;&#039;collapsed&#039;&#039;&#039; to &#039;&#039;&#039;sidemenu&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:31--&amp;gt;&lt;br /&gt;
Once the changes are done, the sidemenu of the survey (the options displayed under the settings tab) will become the following one:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:32--&amp;gt;&lt;br /&gt;
&amp;lt;center&amp;gt;[[File:New survey menu example.png]]&amp;lt;/center&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== I want to change the icons and add new menu entries to the default main menu == &amp;lt;!--T:33--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:34--&amp;gt;&lt;br /&gt;
To do that, you need to configure the LimeSurvey menu entries. To do that, please continue reading the following [[Menu entries configuration|wiki section]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/translate&amp;gt;&lt;/div&gt;</summary>
		<author><name>LimeAJ</name></author>
	</entry>
	<entry>
		<id>https://www.limesurvey.org/manual/index.php?title=Survey_settings&amp;diff=76584</id>
		<title>Survey settings</title>
		<link rel="alternate" type="text/html" href="https://www.limesurvey.org/manual/index.php?title=Survey_settings&amp;diff=76584"/>
		<updated>2017-09-05T13:35:01Z</updated>

		<summary type="html">&lt;p&gt;LimeAJ: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;languages /&amp;gt;&lt;br /&gt;
&amp;lt;translate&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:2--&amp;gt;&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
=Overview= &amp;lt;!--T:3--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:4--&amp;gt;&lt;br /&gt;
Some of these settings can be set when creating a new survey. Click on the Add quick-button [[File:Btn_create_survey.png|100px]] or choose Survey/Create a new survey from the dropdown menu on the top-right  and a &amp;quot;Create new survey&amp;quot; screen will appear. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:36--&amp;gt;&lt;br /&gt;
You can edit all of these settings later again by choosing your survey and clicking General settings &amp;amp; texts in the &#039;Survey properties&#039; dropdown menu of the survey toolbar.&lt;br /&gt;
&lt;br /&gt;
=Settings= &amp;lt;!--T:5--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:6--&amp;gt;&lt;br /&gt;
All survey settings and functions are organized in tabs. The following is a description of each tab and field.&lt;br /&gt;
&lt;br /&gt;
==General== &amp;lt;!--T:7--&amp;gt;&lt;br /&gt;
#&#039;&#039;&#039;Base language&#039;&#039;&#039;: This sets the base language for the survey. Once saved, you cannot change it later. The language-set is the base language for possible translations of the survey. That way you can have multilingual surveys. During survey creation you cannot add additional languages. You will be able do that if you edit the survey properties again, later.&lt;br /&gt;
#&#039;&#039;&#039;Additional languages&#039;&#039;&#039;: To choose additional language. &amp;lt;span class=&amp;quot;alert&amp;quot;&amp;gt;Only available when survey is created.&amp;lt;/span&amp;gt;&lt;br /&gt;
#&#039;&#039;&#039;Title&#039;&#039;&#039;: This is the brief descriptive name of the survey (ie: &amp;quot;Enterprise Bargaining Survey 2003&amp;quot;, or &amp;quot;Views on Ice Cream&amp;quot;). This title will be displayed on every page of the public survey. &lt;br /&gt;
#&#039;&#039;&#039;Description&#039;&#039;&#039;: This allows you to enter a description of the survey. (ie: &amp;quot;A survey to collect your ideas on the next round of enterprise bargaining&amp;quot; or &amp;quot;A survey to find out the popularity of chocolate ice cream&amp;quot;). You can incorporate HTML elements such as images or videos in this section using the WYSIWYG editor. By default, description is used on invitation email.&lt;br /&gt;
#&#039;&#039;&#039;Welcome message&#039;&#039;&#039;: This allows you to enter a message that will display when a participant first logs into your survey. (ie: &amp;quot;Thank you for taking the time to participate in this survey..&amp;quot;) You can incorporate HTML elements such as images or videos in this section using the WYSIWYG editor. &amp;lt;span class=&amp;quot;alert&amp;quot;&amp;gt;Only available at survey creation. After survey creation, it is available in Edit survey text elements.&amp;lt;/span&amp;gt;&lt;br /&gt;
#&#039;&#039;&#039;End message&#039;&#039;&#039;: This allows you to enter a message that will display when a participant completes your survey. (ie: &amp;quot;Thank you for completing our survey. We will publish results soon.&amp;quot;). You can incorporate HTML elements such as images or videos in this section using the WYSIWYG editor. &amp;lt;span class=&amp;quot;alert&amp;quot;&amp;gt;Only available at survey creation. After survey creation, it is available in Edit survey text elements&amp;lt;/span&amp;gt;&lt;br /&gt;
#&#039;&#039;&#039;End URL&#039;&#039;&#039;: This URL will be presented as a link at the end of the survey, and allows you to direct your participants back to your home page (or, in fact, anywhere). The End URL has to be entered with &amp;quot;http://&amp;quot; at the beginning, eg. http://www.limesurvey.org. &amp;lt;br /&amp;gt;You can use they placeholder {SAVEDID}, {TOKEN}, {SID} and {LANG} in this URL.&amp;lt;br /&amp;gt;SAVEDID is the id assigned to this particular submission, TOKEN is the token used to participate in the survey, SID is the survey ID and LANG is the language code&amp;lt;br /&amp;gt;eg. http://www.limesurvey.org/test.php?var1={SAVEDID}&amp;amp;var2;={TOKEN}&amp;amp;var3;={SID}&amp;amp;lang;={LANG} &amp;lt;br /&amp;gt;From version 1.82+ you can use [[URL fields]] with this field to pass parameters from the start URL to then end URL. &amp;lt;br /&amp;gt;You can also use {INSERTANS:SGQA} in this URL (since 1.82+). This allows adding the response to a specific question in the survey to the final url. This can be useful for sending a response to an external script (ie an email address collected during the survey). eg: &amp;quot;http://www.limesurvey.org/test.php?email={INSERTANS:1234X56X7}&amp;quot;.&amp;lt;span class=&amp;quot;alert&amp;quot;&amp;gt;Only available at survey creation. After available in Edit survey text elements&amp;lt;/span&amp;gt;&lt;br /&gt;
#&#039;&#039;&#039;URL description&#039;&#039;&#039;: The description for the link using the End URL.&amp;lt;span class=&amp;quot;alert&amp;quot;&amp;gt;Only available at survey creation. After available in Edit survey text elements&amp;lt;/span&amp;gt;&lt;br /&gt;
#&#039;&#039;&#039;Administrator&#039;&#039;&#039;: This is the name of the contact person who administers the survey. It will be included in emails sent out inviting participants to respond.&lt;br /&gt;
#&#039;&#039;&#039;Admin email&#039;&#039;&#039;: This is the email address of the administrator (as above) and is used as the &#039;From:&#039; address on any emails sent.&amp;lt;br /&amp;gt;NOTE: many hosting providers&#039; SMTP servers will only accept emails whose &#039;From:&#039; address is on a local domain, with the added difficulty that any emails that do not conform to this rule are discarded silently, without any visible error message. If this happens to you, ensure that you are using a provider-based email address in the &#039;Admin email&#039; field. You usually can, if you so desire, set up email forwarding on the provider&#039;s side, so that any messages sent there are relayed to your preferred address.&lt;br /&gt;
#&#039;&#039;&#039;Bounce email&#039;&#039;&#039;: This is the email address where a delivery error notification email should be sent. By default, this is the same as the administrator&#039;s email address. If you want to use a custom script to parse delivery error emails, then use a special Bounce Email address here and automatically process emails reaching this address with your script. This script could then update the Email Status field of the token line corresponding to this email address (see tokens).&lt;br /&gt;
#&#039;&#039;&#039;Fax to&#039;&#039;&#039;: This field is used to give a fax number on the &amp;quot;printable survey&amp;quot; - ie: when you want to send someone a hard copy because they cannot use the online survey.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:8--&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;simplebox&amp;quot;&amp;gt;&#039;&#039;&#039;Caution&#039;&#039;&#039;: the HTML WYSIWYG editor doesn&#039;t allow you to upload files during the survey creation process. Trying to do so will end up with an error message like: &amp;quot;&#039;&#039;This file uploader is disabled&#039;&#039;&amp;quot;. If you need to upload pictures or any other ressources, please do so after survey creation, by editing the newly created survey.&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Presentation &amp;amp; navigation== &amp;lt;!--T:9--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:37--&amp;gt;&lt;br /&gt;
[[File:Survey-settings_presentation-navigation_tab.png]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:38--&amp;gt;&lt;br /&gt;
#&#039;&#039;&#039;Format&#039;&#039;&#039;: Choose from &amp;quot;Question by question&amp;quot;, &amp;quot;Group by group&amp;quot; or &amp;quot;All in one&amp;quot;.&lt;br /&gt;
#*&#039;&#039;&#039;Question by Question&#039;&#039;&#039;: Public survey will display one question per page.&lt;br /&gt;
#*&#039;&#039;&#039;Group by Group&#039;&#039;&#039;: Public survey will display all questions in a group per page. Group at a time surveys still have a separate &amp;quot;welcome&amp;quot; page and &amp;quot;submit&amp;quot; page, like &amp;quot;Question by Question&amp;quot; surveys.&lt;br /&gt;
#*&#039;&#039;&#039;All in one&#039;&#039;&#039;: Public survey will display all questions in one single page. Activated All in one surveys do not have a &amp;quot;welcome&amp;quot; page or &amp;quot;submit&amp;quot; page - the welcome message and submit button all appear on the same page.&lt;br /&gt;
#&#039;&#039;&#039;Template&#039;&#039;&#039;: Choose from the installed templates in your system. The default template is rather dull, but functional. More information on creating your own templates is available [[The template editor|here]].&lt;br /&gt;
#&#039;&#039;&#039;Show welcome screen&#039;&#039;&#039;:  Yes/No. If Yes, then the welcome message defined in Text Elements section will be displayed.    Default is Yes.&lt;br /&gt;
#&#039;&#039;&#039;Navigation delay&#039;&#039;&#039;:  Number of seconds before Previous and Next buttons are enabled.   Default 0 seconds&lt;br /&gt;
#&#039;&#039;&#039;Show &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;&amp;lt;&amp;lt; Prev] button&#039;&#039;&#039;: This option defaults to yes, however if you set it to &amp;quot;No&amp;quot; then users will not have the option of moving to a previous page while completing the survey.&lt;br /&gt;
#&#039;&#039;&#039;Show question index / allow jumping&#039;&#039;&#039;:  Yes/No. Default No.  When Yes, an index will be displayed on the right side.    Users can jump to any section in the survey. In 2.05 the options have changed to Disabled / Incremental / Full. Disabled and Incremental represent the current No and Yes options. Full always shows all groups / questions, this allows the user to freely navigate through the survey. This might not work for all kinds of conditions.&lt;br /&gt;
#&#039;&#039;&#039;Keyboard-less operation&#039;&#039;&#039;: By activating this setting there will be a virtual keyboard available for certain question types.&lt;br /&gt;
#&#039;&#039;&#039;Show progress bar&#039;&#039;&#039;: Yes/No.  Default Yes.   Allow the administrator to turn off the Progress bar&lt;br /&gt;
#&#039;&#039;&#039;Participants may print answers?&#039;&#039;&#039;: This option defaults to no. When it is set to yes, a participant can print a summary of responses at submit time.&lt;br /&gt;
#&#039;&#039;&#039;Public statistics&#039;&#039;&#039;: Yes/No.   Default No.   If set to &amp;quot;Yes&amp;quot; users who have submitted the survey will be presented a link to statistics of the current survey. The admin can set which questions should be included at these statistics by [[Advanced question settings#public_statistics|applying the according question attribute]].&lt;br /&gt;
#&#039;&#039;&#039;Show graphs in public statistics&#039;&#039;&#039;: (&#039;&#039;since 1.80&#039;&#039;) Determines if public statistics for this survey include graphs or only show a tabular overview. Creating graphs for huge surveys with lots of answers takes some time and server resources so this is the switch to turn them on/off (default setting: &#039;&#039;off&#039;&#039;).&lt;br /&gt;
#&#039;&#039;&#039;Automatically load URL when survey complete&#039;&#039;&#039;:  Yes/No.  Default No.   If yes, when the survey is submitted, it will automatically redirect to the End URL. The end URL can be defined in the Text Elements Section. Please note that this only works on an active survey.&lt;br /&gt;
#&#039;&#039;&#039;Show &amp;quot;There are X questions in this survey&amp;quot;&#039;&#039;&#039;:  Yes/No.  Default Yes.   If Yes, the message will be displayed on the Welcome Screen.    This option will not affect the print version.&lt;br /&gt;
#&#039;&#039;&#039;Show group name and/or group description&#039;&#039;&#039;:  Will control the display of Group Names and Descriptions.   This option will not affect the print version. Four Options:&lt;br /&gt;
#*&#039;&#039;&#039;Show Both&#039;&#039;&#039; - Default&lt;br /&gt;
#*&#039;&#039;&#039;Show Group Names Only&#039;&#039;&#039;&lt;br /&gt;
#*&#039;&#039;&#039;Show group description Only&#039;&#039;&#039;&lt;br /&gt;
#*&#039;&#039;&#039;Hide Both&#039;&#039;&#039;&lt;br /&gt;
#&#039;&#039;&#039;Show question number and/or code&#039;&#039;&#039;:&lt;br /&gt;
#*&#039;&#039;&#039;Show Both&#039;&#039;&#039; - Default&lt;br /&gt;
#*&#039;&#039;&#039;Show Question Number Only&#039;&#039;&#039;&lt;br /&gt;
#*&#039;&#039;&#039;Show Question Code Only&#039;&#039;&#039;&lt;br /&gt;
#*&#039;&#039;&#039;Hide Both&#039;&#039;&#039;&lt;br /&gt;
#&#039;&#039;&#039;Show &amp;quot;No answer&amp;quot;&#039;&#039;&#039;: Yes/No.  Default Yes.   When Yes, the No Answer will be displayed as the default option for non-mandatory single-select questions. Be aware that if you switch this off, the participant won&#039;t be able to unselect a chosen answer option in a non-mandatory question.&lt;br /&gt;
&lt;br /&gt;
==Publication &amp;amp; access control== &amp;lt;!--T:10--&amp;gt;&lt;br /&gt;
#&#039;&#039;&#039;List survey publicly&#039;&#039;&#039;: Yes/No.  Default No. When it is set to yes, your survey will be listed in the &#039;available surveys&#039; portal&lt;br /&gt;
# &#039;&#039;&#039;Start date/time&#039;&#039;&#039;: Set this to some date if you want your survey to start on a certain date. The survey will start on midnight of that day and only then will people be able to answer to it. To disable this just clear the date from the input field.&lt;br /&gt;
#&#039;&#039;&#039;Expiry date/time&#039;&#039;&#039;: Set this to some date if you want your survey to expire on a special date. This is the last date on which the public survey script will let people participate. (Example: If you set it for the 31st of December, then people will no longer be able to use the survey script on the 1st of January). To disable this just clear the date from the input field.&lt;br /&gt;
#&#039;&#039;&#039;Set cookie to prevent repeated participation?&#039;&#039;&#039;: If you set this to &#039;Yes&#039;, and your survey does not use a tokens table to control participant access, then a cookie will be saved to the client computer of each survey participant once they have submitted a survey. This cookie will stop the same user on that computer from accessing the survey more than once. There are inherent limitations in the &#039;security&#039; strength of such a system, but, in general, it allows you to retain some control over multiple entries on public surveys.&lt;br /&gt;
#&#039;&#039;&#039;Use CAPTCHA for&#039;&#039;&#039;: With this option you can decide when you want a CAPTCHA to be used. Default is to enable CAPTCHA only for the public Registration page, but you can also enable it before accessing the survey, and before Load/Saving partial answers.&lt;br /&gt;
&lt;br /&gt;
==Notification &amp;amp; data management== &amp;lt;!--T:11--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:39--&amp;gt;&lt;br /&gt;
[[File:Survey-settings_notifications-tab.png]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:40--&amp;gt;&lt;br /&gt;
#&#039;&#039;&#039;Send basic admin notification email to:&#039;&#039;&#039; and &#039;&#039;&#039;Send detailed admin notification email to:&#039;&#039;&#039; These fields allow you to send notifications or survey responses to any email addresses once the survey is submitted. You can edit the templates for these emails under &#039;Email templates&#039;. Multiple recipients can be set by separating the entries with a semicolon (;) - eg &amp;quot;yourname@test.com; myname@test.com;hisname@test.com&amp;quot; OR when using placeholders &amp;quot;yourname@test.com;{INSERTANS:82733X12X73};{TOKEN:EMAIL}&amp;quot;. To sedn an email to the administrator email of the survey : you must use {ADMINEMAIL}. There are different ways for entering an address:&lt;br /&gt;
##Enter a specific &#039;&#039;email address&#039;&#039; (ie: yourname@test.com)&lt;br /&gt;
##Enter a &#039;&#039;SGQA code&#039;&#039; and the response will be sent to an email address entered as an answer to that particular question (use the format {INSERTANS:9999X88X12}, in the same way you would [[Adding a question#Information from previous answers|Re-use information from previous answers]])&lt;br /&gt;
##Enter a &#039;&#039;Token code&#039;&#039; (only possible if your survey is &#039;&#039;not&#039;&#039; anonymous) and the response will be sent to an email address retrieved from a token field (use the format {TOKEN:EMAIL} or {TOKEN:ATTRIBUTE_1} in the same way you would [[Adding a question#Information from tokens table|Re-use Information from the Tokens Table]])&lt;br /&gt;
##&#039;&#039;As of Version 1.92:&#039;&#039; Enter a valid expression conforming to [[Expression Manager|Expression Manager]] syntax.  This lets you use question code instead of SGQA syntax (for easier readability), plus conditional logic (e.g. route the notifications to different people depending upon the data entered into the survey).&lt;br /&gt;
#&#039;&#039;&#039;Date stamp?&#039;&#039;&#039;: This field allows you to determine whether the survey will datestamp all responses. If you choose &amp;quot;Yes&amp;quot;, then when a response is submitted, a field will be included in that response indicating the time and date that the response was made. (See configuration settings for $timeadjust setting.)&lt;br /&gt;
#&#039;&#039;&#039;Save IP address?&#039;&#039;&#039;: This field allows you to determine whether the survey will save an IP-address for all responses. If you choose &amp;quot;Yes&amp;quot;, then when a response is submitted, a field will be included in that response indicating the ip-address of the participant.&lt;br /&gt;
#&#039;&#039;&#039;Save referrer URL?&#039;&#039;&#039;: This field allows you to determine whether the survey will save the referrer URL for all responses. If you choose &amp;quot;Yes&amp;quot;, then when a response is submitted, a field will be included in that response where this URL is saved. A referrer URL is the URL from which the user was led to your survey URL.&lt;br /&gt;
#&#039;&#039;&#039;Enable assessment mode?&#039;&#039;&#039;: With this setting you can enable/disable [[Assessments|assessments]] for this survey.&lt;br /&gt;
#&#039;&#039;&#039;Save timings&#039;&#039;&#039;: If activate then on survey activation a separate table will be created where timings for your questions will be saved, e.g. how long a user stays on one page during taking the survey.&lt;br /&gt;
#&#039;&#039;&#039;Participant may save and resume later?&#039;&#039;&#039;: This setting allows a participant to save his responses and resume to answer the survey at a later time. Please note that this makes most sense with open surveys or surveys with anonymized answer. If you are using tokens and the survey is not anonymous in most cases it is better to activate &#039;Token-based response persistence&#039; in the token tab.&lt;br /&gt;
#&#039;&#039;&#039;Google Analytics Tracking ID for this survey&#039;&#039;&#039;:  Allows for integration with Google Analytics. The tracking ID can be inserted into templates using {GOOGLE_ANALYTICS_API_KEY}. The full JavaScript that Google Analytics expects (including the key) can be included in templates via {GOOGLE_ANALYTICS_JAVASCRIPT}&lt;br /&gt;
#&#039;&#039;&#039;Google Analytics Style for this Survey&#039;&#039;&#039;:  Choices are:&lt;br /&gt;
##&#039;&#039;&#039;Do not use Google Analytics&#039;&#039;&#039; - so {GOOGLE_ANALYTICS_JAVASCRIPT} is an empty string&lt;br /&gt;
##&#039;&#039;&#039;Default Google Analytics&#039;&#039;&#039; - {GOOGLE_ANALYTICS_JAVASCRIPT} uses the standard Google Analytics code, inserting the proper Google Analytics Key&lt;br /&gt;
##&#039;&#039;&#039;SurveyName-&amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;SID]/GroupName&#039;&#039;&#039; - {GOOGLE_ANALYTICS_JAVASCRIPT} contains customized Google Analytics code to log the URL as {SURVEYNAME}-&amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;{SID}]/{GROUPNAME}.  This can be  helpful if you want to analyze navigation paths through your survey, time spent per page, and drop-off rates per page.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:12--&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Google API howto&#039;&#039;&#039;:&lt;br /&gt;
# Register/login on Google Analytics (GA): [http://www.google.com/analytics/ www.google.com/analytics/]&lt;br /&gt;
# Create a tracking ID (the site should not point to the survey, but to the part before &#039;index.php?&#039;) The tracking ID should be UA-xxxxx.&lt;br /&gt;
# Go to your survey&#039;s global settings in LimeSurvey.&lt;br /&gt;
# Put the tracking ID in appropriate field (Google Analytics tracking ID). It&#039;s probably the best to set GA style to track all pages as you can have more info.&lt;br /&gt;
# You don&#039;t need to do anything in shipped templates, as the {GOOGLE_ANALYTICS_JAVASCRIPT} part is already there.&lt;br /&gt;
# Activate the survey.&lt;br /&gt;
# Do the survey.&lt;br /&gt;
# Go to GA panel mainsite. (select appropriate account in left-hand upper corner if you have more than one). You should see some graphs with the statistics. Beware of the dates in upper right corner.&lt;br /&gt;
&lt;br /&gt;
==Tokens== &amp;lt;!--T:13--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:30--&amp;gt;&lt;br /&gt;
*&#039;&#039;&#039;Anonymized responses?&#039;&#039;&#039;: This allows you to determine whether responses to your survey are matched up with information from your surveys tokens table, or kept &#039;anonymous&#039;. The default is &#039;No&#039;. If you choose &#039;Yes&#039; then your survey is set to radically anonymize responses - there is really no way to connect answers and participants. Even the admin can&#039;t link response data and participant/token data. However you will always be able to specifically view each response entered by your participants in the survey. Thus individual, but anonymous, statistics is still possible to do. &#039;&#039;&#039;&#039;&#039;Attention:&#039;&#039;&#039;&#039;&#039;: If this feature is activated the response submission date and the token completed date are always set to 1980-01-01 00:00, no matter of other settings. Why? Invalidating the submission date ensures no match with webserver logs where the token key might show up when a survey is started. Invalidating the token completed date makes sure that you can&#039;t align the order of submitted responses to the order of the token date/time.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:31--&amp;gt;&lt;br /&gt;
*&#039;&#039;&#039;Enable token-based response persistence&#039;&#039;&#039;: If your survey uses tokens and your responses are not anonymized, you may want to enable this feature. If you turn this on, your participants will be able to leave the survey and resume later at any time without using the &#039;Resume later&#039; function - for example if they get distracted or their browser crashes. Upon clicking the invitation link again, they will find their survey answers still in place when they return to the survey, and will even find themselves on the same page where they were before leaving.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:32--&amp;gt;&lt;br /&gt;
*&#039;&#039;&#039;Allow multiple responses or update responses with one token?&#039;&#039;&#039;: Default: No. If you activate this setting, participants will be able to return to their survey by clicking the invitation link, even if they have already submitted the survey. If the survey is anonymous or &amp;quot;Enable token-based response persistence&amp;quot; is set to NO, this will add a new response. If the survey is not anonymous and &amp;quot;Enable token-based response persistence&amp;quot; is Yes, the user will update the existing responses.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:33--&amp;gt;&lt;br /&gt;
*&#039;&#039;&#039;Allow public registration&#039;&#039;&#039;: If you use tokens to control access to your survey, the only people who can use the survey are those who have an entry and a unique token from the token table. If you would like to use tokens, but also allow public registration, set this to &amp;quot;Yes&amp;quot;.  The &amp;quot;Yes&amp;quot; setting will allow a visitor to register his name and email address. The script will create a new entry in your tokens table for this person, then send them an invitation email. The script will ensure that only one person per email address can complete your survey.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:34--&amp;gt;&lt;br /&gt;
*&#039;&#039;&#039;Use HTML format for token emails?&#039;&#039;&#039;: When set to yes, all emails sent by the token management interface (invite, reminder, confirmation) will be formatted as HTML. You&#039;ll then be able to use rich formatting for this emails. Default is Yes at survey creation. Caution, when you switch on/off this feature, you&#039;ll have to double check that your email templates are still displayed as you want.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:35--&amp;gt;&lt;br /&gt;
*&#039;&#039;&#039;Set token length to&#039;&#039;&#039;: Usually you don&#039;t need to change this, the default setting of 15 digits (max. supported value: 35) is fine. If changing this setting please enter a number (X) which should be greater than 5 (if the number entered is &amp;lt;5 it will be converted to the default value of 15). When generating tokens all tokens will use a length of X digits.&lt;br /&gt;
&lt;br /&gt;
==Import== &amp;lt;!--T:14--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:15--&amp;gt;&lt;br /&gt;
Alternatively you can [[Importing a survey structure|import a survey structure]] from this tab on survey creation. You have the option to let LimeSurvey automatically convert relative URLs to local images/media files and INSERTANS tags (recommended).&lt;br /&gt;
&lt;br /&gt;
==Copy== &amp;lt;!--T:16--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:17--&amp;gt;&lt;br /&gt;
Alternatively you can copy an existing survey from this tab on survey creation. You have the option to let LimeSurvey automatically convert relative URLs to local images/media files and INSERTANS tags (recommended). The other options are pretty self-explaining. Please note that when copying a survey the start date and the end date of a survey cleared.&lt;br /&gt;
&lt;br /&gt;
==Panel integration (URL parameters)== &amp;lt;!--T:18--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:19--&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;simplebox&amp;quot;&amp;gt; Please note that this tab is currently not visible on survey creation but only when you edit the survey settings after saving them for the first time.&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:41--&amp;gt;&lt;br /&gt;
On this tab you can set which additional URL parameters will be accepted by your survey (these parameters would be attached to the general survey start URL). This is important if you integrate with a professional survey panel provider that provides the participants for your survey. They usually hand over a unqiue ID with every participant and you will need to save/handle this unique ID for reference. Also with some providers the unique ID of the participant (bdropping out due to quota or finishing the survey) needs to be sent back to the panel provider in the survey end URL. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:20--&amp;gt;&lt;br /&gt;
If you like you can also save the value as a response of a &amp;quot;Short text question&amp;quot; or &amp;quot;Multiple short text question&amp;quot; type (you will be able to select any short text question to save it to). Even if you do NOT save the value of the URL parameter you will be able to use this parameter in the end URL. Please have a look at the documentation of the [[URL_fields#Passthrough_fields_.28LimeSurvey_2.x_or_later.29|End-URL]] for further information.&lt;br /&gt;
&lt;br /&gt;
==Resources== &amp;lt;!--T:21--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:22--&amp;gt;&lt;br /&gt;
This tab lets you manage files (pictures, media files) that were uploaded in the HTML Editor and it is only visible if you edit a survey - not during survey creation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:23--&amp;gt;&lt;br /&gt;
You can:&lt;br /&gt;
* Browse available files&lt;br /&gt;
* Export files as a ZIP archive&lt;br /&gt;
* Import a ZIP archive of files&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:24--&amp;gt;&lt;br /&gt;
Important hints:&lt;br /&gt;
* Authorized files extensions are defined in config-defaults.php.&lt;br /&gt;
* Files for the survey are in the upload/surveys/&amp;lt;sid&amp;gt; subdirectory.&lt;br /&gt;
* Uploaded files will only been seen while browsing resources on this survey (groups, questions, answers) not in other surveys or objects (labels).&lt;br /&gt;
* Do not expect this limited visibility to ensure confidentiality of the resources as they are reachable with a simple browser to anyone who know the URL to the file.&lt;br /&gt;
* You can&#039;t import a ZIP file containing subdirectories.&lt;br /&gt;
&lt;br /&gt;
=Additional languages= &amp;lt;!--T:25--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:26--&amp;gt;&lt;br /&gt;
To add more languages to a survey you have to create and save it - then edit it again. Now you can add and remove additional languages to the survey. If you remove a language from a survey the complete contents of that language in that survey is deleted permanently so be careful what you are doing.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:27--&amp;gt;&lt;br /&gt;
By clicking on the button &#039;Save and continue&#039; on the first page in the survey settings you will be taken to the language-specific page which lets you change all texts for each language like &#039;&#039;Survey name&#039;&#039;, &#039;&#039;Welcome Text&#039;&#039;, etc. You can also edit the date format which should be used for a certain language.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/translate&amp;gt;&lt;/div&gt;</summary>
		<author><name>LimeAJ</name></author>
	</entry>
	<entry>
		<id>https://www.limesurvey.org/manual/index.php?title=Survey_settings&amp;diff=76583</id>
		<title>Survey settings</title>
		<link rel="alternate" type="text/html" href="https://www.limesurvey.org/manual/index.php?title=Survey_settings&amp;diff=76583"/>
		<updated>2017-09-05T13:34:17Z</updated>

		<summary type="html">&lt;p&gt;LimeAJ: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;languages /&amp;gt;&lt;br /&gt;
&amp;lt;translate&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:2--&amp;gt;&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
=Overview= &amp;lt;!--T:3--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:4--&amp;gt;&lt;br /&gt;
Some of these settings can be set when creating a new survey. Click on the Add quick-button [[File:Btn_create_survey.png|100px]] or choose Survey/Create a new survey from the dropdown menu on the top-right  and a &amp;quot;Create new survey&amp;quot; screen will appear. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:36--&amp;gt;&lt;br /&gt;
You can edit all of these settings later again by choosing your survey and clicking General settings &amp;amp; texts in the &#039;Survey properties&#039; dropdown menu of the survey toolbar.&lt;br /&gt;
&lt;br /&gt;
=Settings= &amp;lt;!--T:5--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:6--&amp;gt;&lt;br /&gt;
All survey settings and functions are organized in tabs. The following is a description of each tab and field.&lt;br /&gt;
&lt;br /&gt;
==General== &amp;lt;!--T:7--&amp;gt;&lt;br /&gt;
#&#039;&#039;&#039;Base language&#039;&#039;&#039;: This sets the base language for the survey. Once saved, you cannot change it later. The language-set is the base language for possible translations of the survey. That way you can have multilingual surveys. During survey creation you cannot add additional languages. You will be able do that if you edit the survey properties again, later.&lt;br /&gt;
#&#039;&#039;&#039;Additional languages&#039;&#039;&#039;: To choose additional language. &amp;lt;span class=&amp;quot;alert&amp;quot;&amp;gt;Only available when survey is created.&amp;lt;/span&amp;gt;&lt;br /&gt;
#&#039;&#039;&#039;Title&#039;&#039;&#039;: This is the brief descriptive name of the survey (ie: &amp;quot;Enterprise Bargaining Survey 2003&amp;quot;, or &amp;quot;Views on Ice Cream&amp;quot;). This title will be displayed on every page of the public survey. &lt;br /&gt;
#&#039;&#039;&#039;Description&#039;&#039;&#039;: This allows you to enter a description of the survey. (ie: &amp;quot;A survey to collect your ideas on the next round of enterprise bargaining&amp;quot; or &amp;quot;A survey to find out the popularity of chocolate ice cream&amp;quot;). You can incorporate HTML elements such as images or videos in this section using the WYSIWYG editor. By default, description is used on invitation email.&lt;br /&gt;
#&#039;&#039;&#039;Welcome message&#039;&#039;&#039;: This allows you to enter a message that will display when a participant first logs into your survey. (ie: &amp;quot;Thank you for taking the time to participate in this survey..&amp;quot;) You can incorporate HTML elements such as images or videos in this section using the WYSIWYG editor.&amp;lt;span class=&amp;quot;alert&amp;quot;&amp;gt;Only available at survey creation. After available in Edit survey text elements&amp;lt;/span&amp;gt;&lt;br /&gt;
#&#039;&#039;&#039;End message&#039;&#039;&#039;: This allows you to enter a message that will display when a participant completes your survey. (ie: &amp;quot;Thank you for completing our survey. We will publish results soon.&amp;quot;). You can incorporate HTML elements such as images or videos in this section using the WYSIWYG editor.&amp;lt;span class=&amp;quot;alert&amp;quot;&amp;gt;Only available at survey creation. After survey creation, it is available in Edit survey text elements&amp;lt;/span&amp;gt;&lt;br /&gt;
#&#039;&#039;&#039;End URL&#039;&#039;&#039;: This URL will be presented as a link at the end of the survey, and allows you to direct your participants back to your home page (or, in fact, anywhere). The End URL has to be entered with &amp;quot;http://&amp;quot; at the beginning, eg. http://www.limesurvey.org. &amp;lt;br /&amp;gt;You can use they placeholder {SAVEDID}, {TOKEN}, {SID} and {LANG} in this URL.&amp;lt;br /&amp;gt;SAVEDID is the id assigned to this particular submission, TOKEN is the token used to participate in the survey, SID is the survey ID and LANG is the language code&amp;lt;br /&amp;gt;eg. http://www.limesurvey.org/test.php?var1={SAVEDID}&amp;amp;var2;={TOKEN}&amp;amp;var3;={SID}&amp;amp;lang;={LANG} &amp;lt;br /&amp;gt;From version 1.82+ you can use [[URL fields]] with this field to pass parameters from the start URL to then end URL. &amp;lt;br /&amp;gt;You can also use {INSERTANS:SGQA} in this URL (since 1.82+). This allows adding the response to a specific question in the survey to the final url. This can be useful for sending a response to an external script (ie an email address collected during the survey). eg: &amp;quot;http://www.limesurvey.org/test.php?email={INSERTANS:1234X56X7}&amp;quot;.&amp;lt;span class=&amp;quot;alert&amp;quot;&amp;gt;Only available at survey creation. After available in Edit survey text elements&amp;lt;/span&amp;gt;&lt;br /&gt;
#&#039;&#039;&#039;URL description&#039;&#039;&#039;: The description for the link using the End URL.&amp;lt;span class=&amp;quot;alert&amp;quot;&amp;gt;Only available at survey creation. After available in Edit survey text elements&amp;lt;/span&amp;gt;&lt;br /&gt;
#&#039;&#039;&#039;Administrator&#039;&#039;&#039;: This is the name of the contact person who administers the survey. It will be included in emails sent out inviting participants to respond.&lt;br /&gt;
#&#039;&#039;&#039;Admin email&#039;&#039;&#039;: This is the email address of the administrator (as above) and is used as the &#039;From:&#039; address on any emails sent.&amp;lt;br /&amp;gt;NOTE: many hosting providers&#039; SMTP servers will only accept emails whose &#039;From:&#039; address is on a local domain, with the added difficulty that any emails that do not conform to this rule are discarded silently, without any visible error message. If this happens to you, ensure that you are using a provider-based email address in the &#039;Admin email&#039; field. You usually can, if you so desire, set up email forwarding on the provider&#039;s side, so that any messages sent there are relayed to your preferred address.&lt;br /&gt;
#&#039;&#039;&#039;Bounce email&#039;&#039;&#039;: This is the email address where a delivery error notification email should be sent. By default, this is the same as the administrator&#039;s email address. If you want to use a custom script to parse delivery error emails, then use a special Bounce Email address here and automatically process emails reaching this address with your script. This script could then update the Email Status field of the token line corresponding to this email address (see tokens).&lt;br /&gt;
#&#039;&#039;&#039;Fax to&#039;&#039;&#039;: This field is used to give a fax number on the &amp;quot;printable survey&amp;quot; - ie: when you want to send someone a hard copy because they cannot use the online survey.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:8--&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;simplebox&amp;quot;&amp;gt;&#039;&#039;&#039;Caution&#039;&#039;&#039;: the HTML WYSIWYG editor doesn&#039;t allow you to upload files during the survey creation process. Trying to do so will end up with an error message like: &amp;quot;&#039;&#039;This file uploader is disabled&#039;&#039;&amp;quot;. If you need to upload pictures or any other ressources, please do so after survey creation, by editing the newly created survey.&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Presentation &amp;amp; navigation== &amp;lt;!--T:9--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:37--&amp;gt;&lt;br /&gt;
[[File:Survey-settings_presentation-navigation_tab.png]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:38--&amp;gt;&lt;br /&gt;
#&#039;&#039;&#039;Format&#039;&#039;&#039;: Choose from &amp;quot;Question by question&amp;quot;, &amp;quot;Group by group&amp;quot; or &amp;quot;All in one&amp;quot;.&lt;br /&gt;
#*&#039;&#039;&#039;Question by Question&#039;&#039;&#039;: Public survey will display one question per page.&lt;br /&gt;
#*&#039;&#039;&#039;Group by Group&#039;&#039;&#039;: Public survey will display all questions in a group per page. Group at a time surveys still have a separate &amp;quot;welcome&amp;quot; page and &amp;quot;submit&amp;quot; page, like &amp;quot;Question by Question&amp;quot; surveys.&lt;br /&gt;
#*&#039;&#039;&#039;All in one&#039;&#039;&#039;: Public survey will display all questions in one single page. Activated All in one surveys do not have a &amp;quot;welcome&amp;quot; page or &amp;quot;submit&amp;quot; page - the welcome message and submit button all appear on the same page.&lt;br /&gt;
#&#039;&#039;&#039;Template&#039;&#039;&#039;: Choose from the installed templates in your system. The default template is rather dull, but functional. More information on creating your own templates is available [[The template editor|here]].&lt;br /&gt;
#&#039;&#039;&#039;Show welcome screen&#039;&#039;&#039;:  Yes/No. If Yes, then the welcome message defined in Text Elements section will be displayed.    Default is Yes.&lt;br /&gt;
#&#039;&#039;&#039;Navigation delay&#039;&#039;&#039;:  Number of seconds before Previous and Next buttons are enabled.   Default 0 seconds&lt;br /&gt;
#&#039;&#039;&#039;Show &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;&amp;lt;&amp;lt; Prev] button&#039;&#039;&#039;: This option defaults to yes, however if you set it to &amp;quot;No&amp;quot; then users will not have the option of moving to a previous page while completing the survey.&lt;br /&gt;
#&#039;&#039;&#039;Show question index / allow jumping&#039;&#039;&#039;:  Yes/No. Default No.  When Yes, an index will be displayed on the right side.    Users can jump to any section in the survey. In 2.05 the options have changed to Disabled / Incremental / Full. Disabled and Incremental represent the current No and Yes options. Full always shows all groups / questions, this allows the user to freely navigate through the survey. This might not work for all kinds of conditions.&lt;br /&gt;
#&#039;&#039;&#039;Keyboard-less operation&#039;&#039;&#039;: By activating this setting there will be a virtual keyboard available for certain question types.&lt;br /&gt;
#&#039;&#039;&#039;Show progress bar&#039;&#039;&#039;: Yes/No.  Default Yes.   Allow the administrator to turn off the Progress bar&lt;br /&gt;
#&#039;&#039;&#039;Participants may print answers?&#039;&#039;&#039;: This option defaults to no. When it is set to yes, a participant can print a summary of responses at submit time.&lt;br /&gt;
#&#039;&#039;&#039;Public statistics&#039;&#039;&#039;: Yes/No.   Default No.   If set to &amp;quot;Yes&amp;quot; users who have submitted the survey will be presented a link to statistics of the current survey. The admin can set which questions should be included at these statistics by [[Advanced question settings#public_statistics|applying the according question attribute]].&lt;br /&gt;
#&#039;&#039;&#039;Show graphs in public statistics&#039;&#039;&#039;: (&#039;&#039;since 1.80&#039;&#039;) Determines if public statistics for this survey include graphs or only show a tabular overview. Creating graphs for huge surveys with lots of answers takes some time and server resources so this is the switch to turn them on/off (default setting: &#039;&#039;off&#039;&#039;).&lt;br /&gt;
#&#039;&#039;&#039;Automatically load URL when survey complete&#039;&#039;&#039;:  Yes/No.  Default No.   If yes, when the survey is submitted, it will automatically redirect to the End URL. The end URL can be defined in the Text Elements Section. Please note that this only works on an active survey.&lt;br /&gt;
#&#039;&#039;&#039;Show &amp;quot;There are X questions in this survey&amp;quot;&#039;&#039;&#039;:  Yes/No.  Default Yes.   If Yes, the message will be displayed on the Welcome Screen.    This option will not affect the print version.&lt;br /&gt;
#&#039;&#039;&#039;Show group name and/or group description&#039;&#039;&#039;:  Will control the display of Group Names and Descriptions.   This option will not affect the print version. Four Options:&lt;br /&gt;
#*&#039;&#039;&#039;Show Both&#039;&#039;&#039; - Default&lt;br /&gt;
#*&#039;&#039;&#039;Show Group Names Only&#039;&#039;&#039;&lt;br /&gt;
#*&#039;&#039;&#039;Show group description Only&#039;&#039;&#039;&lt;br /&gt;
#*&#039;&#039;&#039;Hide Both&#039;&#039;&#039;&lt;br /&gt;
#&#039;&#039;&#039;Show question number and/or code&#039;&#039;&#039;:&lt;br /&gt;
#*&#039;&#039;&#039;Show Both&#039;&#039;&#039; - Default&lt;br /&gt;
#*&#039;&#039;&#039;Show Question Number Only&#039;&#039;&#039;&lt;br /&gt;
#*&#039;&#039;&#039;Show Question Code Only&#039;&#039;&#039;&lt;br /&gt;
#*&#039;&#039;&#039;Hide Both&#039;&#039;&#039;&lt;br /&gt;
#&#039;&#039;&#039;Show &amp;quot;No answer&amp;quot;&#039;&#039;&#039;: Yes/No.  Default Yes.   When Yes, the No Answer will be displayed as the default option for non-mandatory single-select questions. Be aware that if you switch this off, the participant won&#039;t be able to unselect a chosen answer option in a non-mandatory question.&lt;br /&gt;
&lt;br /&gt;
==Publication &amp;amp; access control== &amp;lt;!--T:10--&amp;gt;&lt;br /&gt;
#&#039;&#039;&#039;List survey publicly&#039;&#039;&#039;: Yes/No.  Default No. When it is set to yes, your survey will be listed in the &#039;available surveys&#039; portal&lt;br /&gt;
# &#039;&#039;&#039;Start date/time&#039;&#039;&#039;: Set this to some date if you want your survey to start on a certain date. The survey will start on midnight of that day and only then will people be able to answer to it. To disable this just clear the date from the input field.&lt;br /&gt;
#&#039;&#039;&#039;Expiry date/time&#039;&#039;&#039;: Set this to some date if you want your survey to expire on a special date. This is the last date on which the public survey script will let people participate. (Example: If you set it for the 31st of December, then people will no longer be able to use the survey script on the 1st of January). To disable this just clear the date from the input field.&lt;br /&gt;
#&#039;&#039;&#039;Set cookie to prevent repeated participation?&#039;&#039;&#039;: If you set this to &#039;Yes&#039;, and your survey does not use a tokens table to control participant access, then a cookie will be saved to the client computer of each survey participant once they have submitted a survey. This cookie will stop the same user on that computer from accessing the survey more than once. There are inherent limitations in the &#039;security&#039; strength of such a system, but, in general, it allows you to retain some control over multiple entries on public surveys.&lt;br /&gt;
#&#039;&#039;&#039;Use CAPTCHA for&#039;&#039;&#039;: With this option you can decide when you want a CAPTCHA to be used. Default is to enable CAPTCHA only for the public Registration page, but you can also enable it before accessing the survey, and before Load/Saving partial answers.&lt;br /&gt;
&lt;br /&gt;
==Notification &amp;amp; data management== &amp;lt;!--T:11--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:39--&amp;gt;&lt;br /&gt;
[[File:Survey-settings_notifications-tab.png]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:40--&amp;gt;&lt;br /&gt;
#&#039;&#039;&#039;Send basic admin notification email to:&#039;&#039;&#039; and &#039;&#039;&#039;Send detailed admin notification email to:&#039;&#039;&#039; These fields allow you to send notifications or survey responses to any email addresses once the survey is submitted. You can edit the templates for these emails under &#039;Email templates&#039;. Multiple recipients can be set by separating the entries with a semicolon (;) - eg &amp;quot;yourname@test.com; myname@test.com;hisname@test.com&amp;quot; OR when using placeholders &amp;quot;yourname@test.com;{INSERTANS:82733X12X73};{TOKEN:EMAIL}&amp;quot;. To sedn an email to the administrator email of the survey : you must use {ADMINEMAIL}. There are different ways for entering an address:&lt;br /&gt;
##Enter a specific &#039;&#039;email address&#039;&#039; (ie: yourname@test.com)&lt;br /&gt;
##Enter a &#039;&#039;SGQA code&#039;&#039; and the response will be sent to an email address entered as an answer to that particular question (use the format {INSERTANS:9999X88X12}, in the same way you would [[Adding a question#Information from previous answers|Re-use information from previous answers]])&lt;br /&gt;
##Enter a &#039;&#039;Token code&#039;&#039; (only possible if your survey is &#039;&#039;not&#039;&#039; anonymous) and the response will be sent to an email address retrieved from a token field (use the format {TOKEN:EMAIL} or {TOKEN:ATTRIBUTE_1} in the same way you would [[Adding a question#Information from tokens table|Re-use Information from the Tokens Table]])&lt;br /&gt;
##&#039;&#039;As of Version 1.92:&#039;&#039; Enter a valid expression conforming to [[Expression Manager|Expression Manager]] syntax.  This lets you use question code instead of SGQA syntax (for easier readability), plus conditional logic (e.g. route the notifications to different people depending upon the data entered into the survey).&lt;br /&gt;
#&#039;&#039;&#039;Date stamp?&#039;&#039;&#039;: This field allows you to determine whether the survey will datestamp all responses. If you choose &amp;quot;Yes&amp;quot;, then when a response is submitted, a field will be included in that response indicating the time and date that the response was made. (See configuration settings for $timeadjust setting.)&lt;br /&gt;
#&#039;&#039;&#039;Save IP address?&#039;&#039;&#039;: This field allows you to determine whether the survey will save an IP-address for all responses. If you choose &amp;quot;Yes&amp;quot;, then when a response is submitted, a field will be included in that response indicating the ip-address of the participant.&lt;br /&gt;
#&#039;&#039;&#039;Save referrer URL?&#039;&#039;&#039;: This field allows you to determine whether the survey will save the referrer URL for all responses. If you choose &amp;quot;Yes&amp;quot;, then when a response is submitted, a field will be included in that response where this URL is saved. A referrer URL is the URL from which the user was led to your survey URL.&lt;br /&gt;
#&#039;&#039;&#039;Enable assessment mode?&#039;&#039;&#039;: With this setting you can enable/disable [[Assessments|assessments]] for this survey.&lt;br /&gt;
#&#039;&#039;&#039;Save timings&#039;&#039;&#039;: If activate then on survey activation a separate table will be created where timings for your questions will be saved, e.g. how long a user stays on one page during taking the survey.&lt;br /&gt;
#&#039;&#039;&#039;Participant may save and resume later?&#039;&#039;&#039;: This setting allows a participant to save his responses and resume to answer the survey at a later time. Please note that this makes most sense with open surveys or surveys with anonymized answer. If you are using tokens and the survey is not anonymous in most cases it is better to activate &#039;Token-based response persistence&#039; in the token tab.&lt;br /&gt;
#&#039;&#039;&#039;Google Analytics Tracking ID for this survey&#039;&#039;&#039;:  Allows for integration with Google Analytics. The tracking ID can be inserted into templates using {GOOGLE_ANALYTICS_API_KEY}. The full JavaScript that Google Analytics expects (including the key) can be included in templates via {GOOGLE_ANALYTICS_JAVASCRIPT}&lt;br /&gt;
#&#039;&#039;&#039;Google Analytics Style for this Survey&#039;&#039;&#039;:  Choices are:&lt;br /&gt;
##&#039;&#039;&#039;Do not use Google Analytics&#039;&#039;&#039; - so {GOOGLE_ANALYTICS_JAVASCRIPT} is an empty string&lt;br /&gt;
##&#039;&#039;&#039;Default Google Analytics&#039;&#039;&#039; - {GOOGLE_ANALYTICS_JAVASCRIPT} uses the standard Google Analytics code, inserting the proper Google Analytics Key&lt;br /&gt;
##&#039;&#039;&#039;SurveyName-&amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;SID]/GroupName&#039;&#039;&#039; - {GOOGLE_ANALYTICS_JAVASCRIPT} contains customized Google Analytics code to log the URL as {SURVEYNAME}-&amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;{SID}]/{GROUPNAME}.  This can be  helpful if you want to analyze navigation paths through your survey, time spent per page, and drop-off rates per page.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:12--&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Google API howto&#039;&#039;&#039;:&lt;br /&gt;
# Register/login on Google Analytics (GA): [http://www.google.com/analytics/ www.google.com/analytics/]&lt;br /&gt;
# Create a tracking ID (the site should not point to the survey, but to the part before &#039;index.php?&#039;) The tracking ID should be UA-xxxxx.&lt;br /&gt;
# Go to your survey&#039;s global settings in LimeSurvey.&lt;br /&gt;
# Put the tracking ID in appropriate field (Google Analytics tracking ID). It&#039;s probably the best to set GA style to track all pages as you can have more info.&lt;br /&gt;
# You don&#039;t need to do anything in shipped templates, as the {GOOGLE_ANALYTICS_JAVASCRIPT} part is already there.&lt;br /&gt;
# Activate the survey.&lt;br /&gt;
# Do the survey.&lt;br /&gt;
# Go to GA panel mainsite. (select appropriate account in left-hand upper corner if you have more than one). You should see some graphs with the statistics. Beware of the dates in upper right corner.&lt;br /&gt;
&lt;br /&gt;
==Tokens== &amp;lt;!--T:13--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:30--&amp;gt;&lt;br /&gt;
*&#039;&#039;&#039;Anonymized responses?&#039;&#039;&#039;: This allows you to determine whether responses to your survey are matched up with information from your surveys tokens table, or kept &#039;anonymous&#039;. The default is &#039;No&#039;. If you choose &#039;Yes&#039; then your survey is set to radically anonymize responses - there is really no way to connect answers and participants. Even the admin can&#039;t link response data and participant/token data. However you will always be able to specifically view each response entered by your participants in the survey. Thus individual, but anonymous, statistics is still possible to do. &#039;&#039;&#039;&#039;&#039;Attention:&#039;&#039;&#039;&#039;&#039;: If this feature is activated the response submission date and the token completed date are always set to 1980-01-01 00:00, no matter of other settings. Why? Invalidating the submission date ensures no match with webserver logs where the token key might show up when a survey is started. Invalidating the token completed date makes sure that you can&#039;t align the order of submitted responses to the order of the token date/time.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:31--&amp;gt;&lt;br /&gt;
*&#039;&#039;&#039;Enable token-based response persistence&#039;&#039;&#039;: If your survey uses tokens and your responses are not anonymized, you may want to enable this feature. If you turn this on, your participants will be able to leave the survey and resume later at any time without using the &#039;Resume later&#039; function - for example if they get distracted or their browser crashes. Upon clicking the invitation link again, they will find their survey answers still in place when they return to the survey, and will even find themselves on the same page where they were before leaving.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:32--&amp;gt;&lt;br /&gt;
*&#039;&#039;&#039;Allow multiple responses or update responses with one token?&#039;&#039;&#039;: Default: No. If you activate this setting, participants will be able to return to their survey by clicking the invitation link, even if they have already submitted the survey. If the survey is anonymous or &amp;quot;Enable token-based response persistence&amp;quot; is set to NO, this will add a new response. If the survey is not anonymous and &amp;quot;Enable token-based response persistence&amp;quot; is Yes, the user will update the existing responses.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:33--&amp;gt;&lt;br /&gt;
*&#039;&#039;&#039;Allow public registration&#039;&#039;&#039;: If you use tokens to control access to your survey, the only people who can use the survey are those who have an entry and a unique token from the token table. If you would like to use tokens, but also allow public registration, set this to &amp;quot;Yes&amp;quot;.  The &amp;quot;Yes&amp;quot; setting will allow a visitor to register his name and email address. The script will create a new entry in your tokens table for this person, then send them an invitation email. The script will ensure that only one person per email address can complete your survey.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:34--&amp;gt;&lt;br /&gt;
*&#039;&#039;&#039;Use HTML format for token emails?&#039;&#039;&#039;: When set to yes, all emails sent by the token management interface (invite, reminder, confirmation) will be formatted as HTML. You&#039;ll then be able to use rich formatting for this emails. Default is Yes at survey creation. Caution, when you switch on/off this feature, you&#039;ll have to double check that your email templates are still displayed as you want.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:35--&amp;gt;&lt;br /&gt;
*&#039;&#039;&#039;Set token length to&#039;&#039;&#039;: Usually you don&#039;t need to change this, the default setting of 15 digits (max. supported value: 35) is fine. If changing this setting please enter a number (X) which should be greater than 5 (if the number entered is &amp;lt;5 it will be converted to the default value of 15). When generating tokens all tokens will use a length of X digits.&lt;br /&gt;
&lt;br /&gt;
==Import== &amp;lt;!--T:14--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:15--&amp;gt;&lt;br /&gt;
Alternatively you can [[Importing a survey structure|import a survey structure]] from this tab on survey creation. You have the option to let LimeSurvey automatically convert relative URLs to local images/media files and INSERTANS tags (recommended).&lt;br /&gt;
&lt;br /&gt;
==Copy== &amp;lt;!--T:16--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:17--&amp;gt;&lt;br /&gt;
Alternatively you can copy an existing survey from this tab on survey creation. You have the option to let LimeSurvey automatically convert relative URLs to local images/media files and INSERTANS tags (recommended). The other options are pretty self-explaining. Please note that when copying a survey the start date and the end date of a survey cleared.&lt;br /&gt;
&lt;br /&gt;
==Panel integration (URL parameters)== &amp;lt;!--T:18--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:19--&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;simplebox&amp;quot;&amp;gt; Please note that this tab is currently not visible on survey creation but only when you edit the survey settings after saving them for the first time.&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:41--&amp;gt;&lt;br /&gt;
On this tab you can set which additional URL parameters will be accepted by your survey (these parameters would be attached to the general survey start URL). This is important if you integrate with a professional survey panel provider that provides the participants for your survey. They usually hand over a unqiue ID with every participant and you will need to save/handle this unique ID for reference. Also with some providers the unique ID of the participant (bdropping out due to quota or finishing the survey) needs to be sent back to the panel provider in the survey end URL. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:20--&amp;gt;&lt;br /&gt;
If you like you can also save the value as a response of a &amp;quot;Short text question&amp;quot; or &amp;quot;Multiple short text question&amp;quot; type (you will be able to select any short text question to save it to). Even if you do NOT save the value of the URL parameter you will be able to use this parameter in the end URL. Please have a look at the documentation of the [[URL_fields#Passthrough_fields_.28LimeSurvey_2.x_or_later.29|End-URL]] for further information.&lt;br /&gt;
&lt;br /&gt;
==Resources== &amp;lt;!--T:21--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:22--&amp;gt;&lt;br /&gt;
This tab lets you manage files (pictures, media files) that were uploaded in the HTML Editor and it is only visible if you edit a survey - not during survey creation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:23--&amp;gt;&lt;br /&gt;
You can:&lt;br /&gt;
* Browse available files&lt;br /&gt;
* Export files as a ZIP archive&lt;br /&gt;
* Import a ZIP archive of files&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:24--&amp;gt;&lt;br /&gt;
Important hints:&lt;br /&gt;
* Authorized files extensions are defined in config-defaults.php.&lt;br /&gt;
* Files for the survey are in the upload/surveys/&amp;lt;sid&amp;gt; subdirectory.&lt;br /&gt;
* Uploaded files will only been seen while browsing resources on this survey (groups, questions, answers) not in other surveys or objects (labels).&lt;br /&gt;
* Do not expect this limited visibility to ensure confidentiality of the resources as they are reachable with a simple browser to anyone who know the URL to the file.&lt;br /&gt;
* You can&#039;t import a ZIP file containing subdirectories.&lt;br /&gt;
&lt;br /&gt;
=Additional languages= &amp;lt;!--T:25--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:26--&amp;gt;&lt;br /&gt;
To add more languages to a survey you have to create and save it - then edit it again. Now you can add and remove additional languages to the survey. If you remove a language from a survey the complete contents of that language in that survey is deleted permanently so be careful what you are doing.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:27--&amp;gt;&lt;br /&gt;
By clicking on the button &#039;Save and continue&#039; on the first page in the survey settings you will be taken to the language-specific page which lets you change all texts for each language like &#039;&#039;Survey name&#039;&#039;, &#039;&#039;Welcome Text&#039;&#039;, etc. You can also edit the date format which should be used for a certain language.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/translate&amp;gt;&lt;/div&gt;</summary>
		<author><name>LimeAJ</name></author>
	</entry>
	<entry>
		<id>https://www.limesurvey.org/manual/index.php?title=Survey_settings&amp;diff=76582</id>
		<title>Survey settings</title>
		<link rel="alternate" type="text/html" href="https://www.limesurvey.org/manual/index.php?title=Survey_settings&amp;diff=76582"/>
		<updated>2017-09-05T13:26:45Z</updated>

		<summary type="html">&lt;p&gt;LimeAJ: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;languages /&amp;gt;&lt;br /&gt;
&amp;lt;translate&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:2--&amp;gt;&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
=Overview= &amp;lt;!--T:3--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:4--&amp;gt;&lt;br /&gt;
Some of these settings can be set when creating a new survey. Click on the Add quick-button [[File:Btn_create_survey.png|100px]] or choose Survey/Create a new survey from the dropdown menu on the top-right  and a &amp;quot;Create new survey&amp;quot; screen will appear. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:36--&amp;gt;&lt;br /&gt;
You can edit all of these settings later again by choosing your survey and clicking General settings &amp;amp; texts in the &#039;Survey properties&#039; dropdown menu of the survey toolbar.&lt;br /&gt;
&lt;br /&gt;
=Settings= &amp;lt;!--T:5--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:6--&amp;gt;&lt;br /&gt;
All survey settings and functions are organized in tabs. The following is a description of each tab and field.&lt;br /&gt;
&lt;br /&gt;
==General== &amp;lt;!--T:7--&amp;gt;&lt;br /&gt;
#&#039;&#039;&#039;Base language&#039;&#039;&#039;: This sets the base language for the survey. Once saved, you cannot change it later. The language-set is the base language for possible translations of the survey. That way you can have multilingual surveys. During survey creation you cannot add additional languages. You will be able do that if you edit the survey properties again, later.&lt;br /&gt;
#&#039;&#039;&#039;Additional languages&#039;&#039;&#039;: To choose additional language. &amp;lt;span class=&amp;quot;alert&amp;quot;&amp;gt;Only available when survey is created.&amp;lt;/span&amp;gt;&lt;br /&gt;
#&#039;&#039;&#039;Title&#039;&#039;&#039;: This is the brief descriptive name of the survey (ie: &amp;quot;Enterprise Bargaining Survey 2003&amp;quot;, or &amp;quot;Views on Ice Cream&amp;quot;). This title will be displayed on every page of the public survey. &lt;br /&gt;
#&#039;&#039;&#039;Description&#039;&#039;&#039;: This allows you to enter a description of the survey. (ie: &amp;quot;A survey to collect your ideas on the next round of enterprise bargaining&amp;quot; or &amp;quot;A survey to find out the popularity of chocolate ice cream&amp;quot;). You can incorporate HTML elements such as images or videos in this section using the WYSIWYG editor. By default, description is used on invitation email.&lt;br /&gt;
#&#039;&#039;&#039;Welcome message&#039;&#039;&#039;: This allows you to enter a message that will display when a participant first logs into your survey. (ie: &amp;quot;Thank you for taking the time to participate in this survey..&amp;quot;) You can incorporate HTML elements such as images or videos in this section using the WYSIWYG editor.&amp;lt;span class=&amp;quot;alert&amp;quot;&amp;gt;Only available at survey creation. After available in Edit survey text elements&amp;lt;/span&amp;gt;&lt;br /&gt;
#&#039;&#039;&#039;End message&#039;&#039;&#039;: This allows you to enter a message that will display when a participant completes your survey. (ie: &amp;quot;Thank you for completing our survey. We will publish results soon.&amp;quot;). You can incorporate HTML elements such as images or videos in this section using the WYSIWYG editor.&amp;lt;span class=&amp;quot;alert&amp;quot;&amp;gt;Only available at survey creation. After available in Edit survey text elements&amp;lt;/span&amp;gt;&lt;br /&gt;
#&#039;&#039;&#039;End URL&#039;&#039;&#039;: This URL will be presented as a link at the end of the survey, and allows you to direct your participants back to your home page (or, in fact, anywhere). The End URL has to be entered with &amp;quot;http://&amp;quot; at the beginning, eg. http://www.limesurvey.org. &amp;lt;br /&amp;gt;You can use they placeholder {SAVEDID}, {TOKEN}, {SID} and {LANG} in this URL.&amp;lt;br /&amp;gt;SAVEDID is the id assigned to this particular submission, TOKEN is the token used to participate in the survey, SID is the survey ID and LANG is the language code&amp;lt;br /&amp;gt;eg. http://www.limesurvey.org/test.php?var1={SAVEDID}&amp;amp;var2;={TOKEN}&amp;amp;var3;={SID}&amp;amp;lang;={LANG} &amp;lt;br /&amp;gt;From version 1.82+ you can use [[URL fields]] with this field to pass parameters from the start URL to then end URL. &amp;lt;br /&amp;gt;You can also use {INSERTANS:SGQA} in this URL (since 1.82+). This allows adding the response to a specific question in the survey to the final url. This can be useful for sending a response to an external script (ie an email address collected during the survey). eg: &amp;quot;http://www.limesurvey.org/test.php?email={INSERTANS:1234X56X7}&amp;quot;.&amp;lt;span class=&amp;quot;alert&amp;quot;&amp;gt;Only available at survey creation. After available in Edit survey text elements&amp;lt;/span&amp;gt;&lt;br /&gt;
#&#039;&#039;&#039;URL description&#039;&#039;&#039;: The description for the link using the End URL.&amp;lt;span class=&amp;quot;alert&amp;quot;&amp;gt;Only available at survey creation. After available in Edit survey text elements&amp;lt;/span&amp;gt;&lt;br /&gt;
#&#039;&#039;&#039;Administrator&#039;&#039;&#039;: This is the name of the contact person who administers the survey. It will be included in emails sent out inviting participants to respond.&lt;br /&gt;
#&#039;&#039;&#039;Admin email&#039;&#039;&#039;: This is the email address of the administrator (as above) and is used as the &#039;From:&#039; address on any emails sent.&amp;lt;br /&amp;gt;NOTE: many hosting providers&#039; SMTP servers will only accept emails whose &#039;From:&#039; address is on a local domain, with the added difficulty that any emails that do not conform to this rule are discarded silently, without any visible error message. If this happens to you, ensure that you are using a provider-based email address in the &#039;Admin email&#039; field. You usually can, if you so desire, set up email forwarding on the provider&#039;s side, so that any messages sent there are relayed to your preferred address.&lt;br /&gt;
#&#039;&#039;&#039;Bounce email&#039;&#039;&#039;: This is the email address where a delivery error notification email should be sent. By default, this is the same as the administrator&#039;s email address. If you want to use a custom script to parse delivery error emails, then use a special Bounce Email address here and automatically process emails reaching this address with your script. This script could then update the Email Status field of the token line corresponding to this email address (see tokens).&lt;br /&gt;
#&#039;&#039;&#039;Fax to&#039;&#039;&#039;: This field is used to give a fax number on the &amp;quot;printable survey&amp;quot; - ie: when you want to send someone a hard copy because they cannot use the online survey.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:8--&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;simplebox&amp;quot;&amp;gt;&#039;&#039;&#039;Caution&#039;&#039;&#039;: the HTML WYSIWYG editor doesn&#039;t allow you to upload files during the survey creation process. Trying to do so will end up with an error message like: &amp;quot;&#039;&#039;This file uploader is disabled&#039;&#039;&amp;quot;. If you need to upload pictures or any other ressources, please do so after survey creation, by editing the newly created survey.&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Presentation &amp;amp; navigation== &amp;lt;!--T:9--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:37--&amp;gt;&lt;br /&gt;
[[File:Survey-settings_presentation-navigation_tab.png]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:38--&amp;gt;&lt;br /&gt;
#&#039;&#039;&#039;Format&#039;&#039;&#039;: Choose from &amp;quot;Question by question&amp;quot;, &amp;quot;Group by group&amp;quot; or &amp;quot;All in one&amp;quot;.&lt;br /&gt;
#*&#039;&#039;&#039;Question by Question&#039;&#039;&#039;: Public survey will display one question per page.&lt;br /&gt;
#*&#039;&#039;&#039;Group by Group&#039;&#039;&#039;: Public survey will display all questions in a group per page. Group at a time surveys still have a separate &amp;quot;welcome&amp;quot; page and &amp;quot;submit&amp;quot; page, like &amp;quot;Question by Question&amp;quot; surveys.&lt;br /&gt;
#*&#039;&#039;&#039;All in one&#039;&#039;&#039;: Public survey will display all questions in one single page. Activated All in one surveys do not have a &amp;quot;welcome&amp;quot; page or &amp;quot;submit&amp;quot; page - the welcome message and submit button all appear on the same page.&lt;br /&gt;
#&#039;&#039;&#039;Template&#039;&#039;&#039;: Choose from the installed templates in your system. The default template is rather dull, but functional. More information on creating your own templates is available [[The template editor|here]].&lt;br /&gt;
#&#039;&#039;&#039;Show welcome screen&#039;&#039;&#039;:  Yes/No. If Yes, then the welcome message defined in Text Elements section will be displayed.    Default is Yes.&lt;br /&gt;
#&#039;&#039;&#039;Navigation delay&#039;&#039;&#039;:  Number of seconds before Previous and Next buttons are enabled.   Default 0 seconds&lt;br /&gt;
#&#039;&#039;&#039;Show &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;&amp;lt;&amp;lt; Prev] button&#039;&#039;&#039;: This option defaults to yes, however if you set it to &amp;quot;No&amp;quot; then users will not have the option of moving to a previous page while completing the survey.&lt;br /&gt;
#&#039;&#039;&#039;Show question index / allow jumping&#039;&#039;&#039;:  Yes/No. Default No.  When Yes, an index will be displayed on the right side.    Users can jump to any section in the survey. In 2.05 the options have changed to Disabled / Incremental / Full. Disabled and Incremental represent the current No and Yes options. Full always shows all groups / questions, this allows the user to freely navigate through the survey. This might not work for all kinds of conditions.&lt;br /&gt;
#&#039;&#039;&#039;Keyboard-less operation&#039;&#039;&#039;: By activating this setting there will be a virtual keyboard available for certain question types.&lt;br /&gt;
#&#039;&#039;&#039;Show progress bar&#039;&#039;&#039;: Yes/No.  Default Yes.   Allow the administrator to turn off the Progress bar&lt;br /&gt;
#&#039;&#039;&#039;Participants may print answers?&#039;&#039;&#039;: This option defaults to no. When it is set to yes, a participant can print a summary of responses at submit time.&lt;br /&gt;
#&#039;&#039;&#039;Public statistics&#039;&#039;&#039;: Yes/No.   Default No.   If set to &amp;quot;Yes&amp;quot; users who have submitted the survey will be presented a link to statistics of the current survey. The admin can set which questions should be included at these statistics by [[Advanced question settings#public_statistics|applying the according question attribute]].&lt;br /&gt;
#&#039;&#039;&#039;Show graphs in public statistics&#039;&#039;&#039;: (&#039;&#039;since 1.80&#039;&#039;) Determines if public statistics for this survey include graphs or only show a tabular overview. Creating graphs for huge surveys with lots of answers takes some time and server resources so this is the switch to turn them on/off (default setting: &#039;&#039;off&#039;&#039;).&lt;br /&gt;
#&#039;&#039;&#039;Automatically load URL when survey complete&#039;&#039;&#039;:  Yes/No.  Default No.   If yes, when the survey is submitted, it will automatically redirect to the End URL. The end URL can be defined in the Text Elements Section. Please note that this only works on an active survey.&lt;br /&gt;
#&#039;&#039;&#039;Show &amp;quot;There are X questions in this survey&amp;quot;&#039;&#039;&#039;:  Yes/No.  Default Yes.   If Yes, the message will be displayed on the Welcome Screen.    This option will not affect the print version.&lt;br /&gt;
#&#039;&#039;&#039;Show group name and/or group description&#039;&#039;&#039;:  Will control the display of Group Names and Descriptions.   This option will not affect the print version. Four Options:&lt;br /&gt;
#*&#039;&#039;&#039;Show Both&#039;&#039;&#039; - Default&lt;br /&gt;
#*&#039;&#039;&#039;Show Group Names Only&#039;&#039;&#039;&lt;br /&gt;
#*&#039;&#039;&#039;Show group description Only&#039;&#039;&#039;&lt;br /&gt;
#*&#039;&#039;&#039;Hide Both&#039;&#039;&#039;&lt;br /&gt;
#&#039;&#039;&#039;Show question number and/or code&#039;&#039;&#039;:&lt;br /&gt;
#*&#039;&#039;&#039;Show Both&#039;&#039;&#039; - Default&lt;br /&gt;
#*&#039;&#039;&#039;Show Question Number Only&#039;&#039;&#039;&lt;br /&gt;
#*&#039;&#039;&#039;Show Question Code Only&#039;&#039;&#039;&lt;br /&gt;
#*&#039;&#039;&#039;Hide Both&#039;&#039;&#039;&lt;br /&gt;
#&#039;&#039;&#039;Show &amp;quot;No answer&amp;quot;&#039;&#039;&#039;: Yes/No.  Default Yes.   When Yes, the No Answer will be displayed as the default option for non-mandatory single-select questions. Be aware that if you switch this off, the participant won&#039;t be able to unselect a chosen answer option in a non-mandatory question.&lt;br /&gt;
&lt;br /&gt;
==Publication &amp;amp; access control== &amp;lt;!--T:10--&amp;gt;&lt;br /&gt;
#&#039;&#039;&#039;List survey publicly&#039;&#039;&#039;: Yes/No.  Default No. When it is set to yes, your survey will be listed in the &#039;available surveys&#039; portal&lt;br /&gt;
# &#039;&#039;&#039;Start date/time&#039;&#039;&#039;: Set this to some date if you want your survey to start on a certain date. The survey will start on midnight of that day and only then will people be able to answer to it. To disable this just clear the date from the input field.&lt;br /&gt;
#&#039;&#039;&#039;Expiry date/time&#039;&#039;&#039;: Set this to some date if you want your survey to expire on a special date. This is the last date on which the public survey script will let people participate. (Example: If you set it for the 31st of December, then people will no longer be able to use the survey script on the 1st of January). To disable this just clear the date from the input field.&lt;br /&gt;
#&#039;&#039;&#039;Set cookie to prevent repeated participation?&#039;&#039;&#039;: If you set this to &#039;Yes&#039;, and your survey does not use a tokens table to control participant access, then a cookie will be saved to the client computer of each survey participant once they have submitted a survey. This cookie will stop the same user on that computer from accessing the survey more than once. There are inherent limitations in the &#039;security&#039; strength of such a system, but, in general, it allows you to retain some control over multiple entries on public surveys.&lt;br /&gt;
#&#039;&#039;&#039;Use CAPTCHA for&#039;&#039;&#039;: With this option you can decide when you want a CAPTCHA to be used. Default is to enable CAPTCHA only for the public Registration page, but you can also enable it before accessing the survey, and before Load/Saving partial answers.&lt;br /&gt;
&lt;br /&gt;
==Notification &amp;amp; data management== &amp;lt;!--T:11--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:39--&amp;gt;&lt;br /&gt;
[[File:Survey-settings_notifications-tab.png]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:40--&amp;gt;&lt;br /&gt;
#&#039;&#039;&#039;Send basic admin notification email to:&#039;&#039;&#039; and &#039;&#039;&#039;Send detailed admin notification email to:&#039;&#039;&#039; These fields allow you to send notifications or survey responses to any email addresses once the survey is submitted. You can edit the templates for these emails under &#039;Email templates&#039;. Multiple recipients can be set by separating the entries with a semicolon (;) - eg &amp;quot;yourname@test.com; myname@test.com;hisname@test.com&amp;quot; OR when using placeholders &amp;quot;yourname@test.com;{INSERTANS:82733X12X73};{TOKEN:EMAIL}&amp;quot;. To sedn an email to the administrator email of the survey : you must use {ADMINEMAIL}. There are different ways for entering an address:&lt;br /&gt;
##Enter a specific &#039;&#039;email address&#039;&#039; (ie: yourname@test.com)&lt;br /&gt;
##Enter a &#039;&#039;SGQA code&#039;&#039; and the response will be sent to an email address entered as an answer to that particular question (use the format {INSERTANS:9999X88X12}, in the same way you would [[Adding a question#Information from previous answers|Re-use information from previous answers]])&lt;br /&gt;
##Enter a &#039;&#039;Token code&#039;&#039; (only possible if your survey is &#039;&#039;not&#039;&#039; anonymous) and the response will be sent to an email address retrieved from a token field (use the format {TOKEN:EMAIL} or {TOKEN:ATTRIBUTE_1} in the same way you would [[Adding a question#Information from tokens table|Re-use Information from the Tokens Table]])&lt;br /&gt;
##&#039;&#039;As of Version 1.92:&#039;&#039; Enter a valid expression conforming to [[Expression Manager|Expression Manager]] syntax.  This lets you use question code instead of SGQA syntax (for easier readability), plus conditional logic (e.g. route the notifications to different people depending upon the data entered into the survey).&lt;br /&gt;
#&#039;&#039;&#039;Date stamp?&#039;&#039;&#039;: This field allows you to determine whether the survey will datestamp all responses. If you choose &amp;quot;Yes&amp;quot;, then when a response is submitted, a field will be included in that response indicating the time and date that the response was made. (See configuration settings for $timeadjust setting.)&lt;br /&gt;
#&#039;&#039;&#039;Save IP address?&#039;&#039;&#039;: This field allows you to determine whether the survey will save an IP-address for all responses. If you choose &amp;quot;Yes&amp;quot;, then when a response is submitted, a field will be included in that response indicating the ip-address of the participant.&lt;br /&gt;
#&#039;&#039;&#039;Save referrer URL?&#039;&#039;&#039;: This field allows you to determine whether the survey will save the referrer URL for all responses. If you choose &amp;quot;Yes&amp;quot;, then when a response is submitted, a field will be included in that response where this URL is saved. A referrer URL is the URL from which the user was led to your survey URL.&lt;br /&gt;
#&#039;&#039;&#039;Enable assessment mode?&#039;&#039;&#039;: With this setting you can enable/disable [[Assessments|assessments]] for this survey.&lt;br /&gt;
#&#039;&#039;&#039;Save timings&#039;&#039;&#039;: If activate then on survey activation a separate table will be created where timings for your questions will be saved, e.g. how long a user stays on one page during taking the survey.&lt;br /&gt;
#&#039;&#039;&#039;Participant may save and resume later?&#039;&#039;&#039;: This setting allows a participant to save his responses and resume to answer the survey at a later time. Please note that this makes most sense with open surveys or surveys with anonymized answer. If you are using tokens and the survey is not anonymous in most cases it is better to activate &#039;Token-based response persistence&#039; in the token tab.&lt;br /&gt;
#&#039;&#039;&#039;Google Analytics Tracking ID for this survey&#039;&#039;&#039;:  Allows for integration with Google Analytics. The tracking ID can be inserted into templates using {GOOGLE_ANALYTICS_API_KEY}. The full JavaScript that Google Analytics expects (including the key) can be included in templates via {GOOGLE_ANALYTICS_JAVASCRIPT}&lt;br /&gt;
#&#039;&#039;&#039;Google Analytics Style for this Survey&#039;&#039;&#039;:  Choices are:&lt;br /&gt;
##&#039;&#039;&#039;Do not use Google Analytics&#039;&#039;&#039; - so {GOOGLE_ANALYTICS_JAVASCRIPT} is an empty string&lt;br /&gt;
##&#039;&#039;&#039;Default Google Analytics&#039;&#039;&#039; - {GOOGLE_ANALYTICS_JAVASCRIPT} uses the standard Google Analytics code, inserting the proper Google Analytics Key&lt;br /&gt;
##&#039;&#039;&#039;SurveyName-&amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;SID]/GroupName&#039;&#039;&#039; - {GOOGLE_ANALYTICS_JAVASCRIPT} contains customized Google Analytics code to log the URL as {SURVEYNAME}-&amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;{SID}]/{GROUPNAME}.  This can be  helpful if you want to analyze navigation paths through your survey, time spent per page, and drop-off rates per page.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:12--&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Google API howto&#039;&#039;&#039;:&lt;br /&gt;
# Register/login on Google Analytics (GA): [http://www.google.com/analytics/ www.google.com/analytics/]&lt;br /&gt;
# Create a tracking ID (the site should not point to the survey, but to the part before &#039;index.php?&#039;) The tracking ID should be UA-xxxxx.&lt;br /&gt;
# Go to your survey&#039;s global settings in LimeSurvey.&lt;br /&gt;
# Put the tracking ID in appropriate field (Google Analytics tracking ID). It&#039;s probably the best to set GA style to track all pages as you can have more info.&lt;br /&gt;
# You don&#039;t need to do anything in shipped templates, as the {GOOGLE_ANALYTICS_JAVASCRIPT} part is already there.&lt;br /&gt;
# Activate the survey.&lt;br /&gt;
# Do the survey.&lt;br /&gt;
# Go to GA panel mainsite. (select appropriate account in left-hand upper corner if you have more than one). You should see some graphs with the statistics. Beware of the dates in upper right corner.&lt;br /&gt;
&lt;br /&gt;
==Tokens== &amp;lt;!--T:13--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:30--&amp;gt;&lt;br /&gt;
*&#039;&#039;&#039;Anonymized responses?&#039;&#039;&#039;: This allows you to determine whether responses to your survey are matched up with information from your surveys tokens table, or kept &#039;anonymous&#039;. The default is &#039;No&#039;. If you choose &#039;Yes&#039; then your survey is set to radically anonymize responses - there is really no way to connect answers and participants. Even the admin can&#039;t link response data and participant/token data. However you will always be able to specifically view each response entered by your participants in the survey. Thus individual, but anonymous, statistics is still possible to do. &#039;&#039;&#039;&#039;&#039;Attention:&#039;&#039;&#039;&#039;&#039;: If this feature is activated the response submission date and the token completed date are always set to 1980-01-01 00:00, no matter of other settings. Why? Invalidating the submission date ensures no match with webserver logs where the token key might show up when a survey is started. Invalidating the token completed date makes sure that you can&#039;t align the order of submitted responses to the order of the token date/time.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:31--&amp;gt;&lt;br /&gt;
*&#039;&#039;&#039;Enable token-based response persistence&#039;&#039;&#039;: If your survey uses tokens and your responses are not anonymized, you may want to enable this feature. If you turn this on, your participants will be able to leave the survey and resume later at any time without using the &#039;Resume later&#039; function - for example if they get distracted or their browser crashes. Upon clicking the invitation link again, they will find their survey answers still in place when they return to the survey, and will even find themselves on the same page where they were before leaving.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:32--&amp;gt;&lt;br /&gt;
*&#039;&#039;&#039;Allow multiple responses or update responses with one token?&#039;&#039;&#039;: Default: No. If you activate this setting, participants will be able to return to their survey by clicking the invitation link, even if they have already submitted the survey. If the survey is anonymous or &amp;quot;Enable token-based response persistence&amp;quot; is set to NO, this will add a new response. If the survey is not anonymous and &amp;quot;Enable token-based response persistence&amp;quot; is Yes, the user will update the existing responses.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:33--&amp;gt;&lt;br /&gt;
*&#039;&#039;&#039;Allow public registration&#039;&#039;&#039;: If you use tokens to control access to your survey, the only people who can use the survey are those who have an entry and a unique token from the token table. If you would like to use tokens, but also allow public registration, set this to &amp;quot;Yes&amp;quot;.  The &amp;quot;Yes&amp;quot; setting will allow a visitor to register his name and email address. The script will create a new entry in your tokens table for this person, then send them an invitation email. The script will ensure that only one person per email address can complete your survey.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:34--&amp;gt;&lt;br /&gt;
*&#039;&#039;&#039;Use HTML format for token emails?&#039;&#039;&#039;: When set to yes, all emails sent by the token management interface (invite, reminder, confirmation) will be formatted as HTML. You&#039;ll then be able to use rich formatting for this emails. Default is Yes at survey creation. Caution, when you switch on/off this feature, you&#039;ll have to double check that your email templates are still displayed as you want.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:35--&amp;gt;&lt;br /&gt;
*&#039;&#039;&#039;Set token length to&#039;&#039;&#039;: Usually you don&#039;t need to change this, the default setting of 15 digits (max. supported value: 35) is fine. If changing this setting please enter a number (X) which should be greater than 5 (if the number entered is &amp;lt;5 it will be converted to the default value of 15). When generating tokens all tokens will use a length of X digits.&lt;br /&gt;
&lt;br /&gt;
==Import== &amp;lt;!--T:14--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:15--&amp;gt;&lt;br /&gt;
Alternatively you can [[Importing a survey structure|import a survey structure]] from this tab on survey creation. You have the option to let LimeSurvey automatically convert relative URLs to local images/media files and INSERTANS tags (recommended).&lt;br /&gt;
&lt;br /&gt;
==Copy== &amp;lt;!--T:16--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:17--&amp;gt;&lt;br /&gt;
Alternatively you can copy an existing survey from this tab on survey creation. You have the option to let LimeSurvey automatically convert relative URLs to local images/media files and INSERTANS tags (recommended). The other options are pretty self-explaining. Please note that when copying a survey the start date and the end date of a survey cleared.&lt;br /&gt;
&lt;br /&gt;
==Panel integration (URL parameters)== &amp;lt;!--T:18--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:19--&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;simplebox&amp;quot;&amp;gt; Please note that this tab is currently not visible on survey creation but only when you edit the survey settings after saving them for the first time.&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:41--&amp;gt;&lt;br /&gt;
On this tab you can set which additional URL parameters will be accepted by your survey (these parameters would be attached to the general survey start URL). This is important if you integrate with a professional survey panel provider that provides the participants for your survey. They usually hand over a unqiue ID with every participant and you will need to save/handle this unique ID for reference. Also with some providers the unique ID of the participant (bdropping out due to quota or finishing the survey) needs to be sent back to the panel provider in the survey end URL. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:20--&amp;gt;&lt;br /&gt;
If you like you can also save the value as a response of a &amp;quot;Short text question&amp;quot; or &amp;quot;Multiple short text question&amp;quot; type (you will be able to select any short text question to save it to). Even if you do NOT save the value of the URL parameter you will be able to use this parameter in the end URL. Please have a look at the documentation of the [[URL_fields#Passthrough_fields_.28LimeSurvey_2.x_or_later.29|End-URL]] for further information.&lt;br /&gt;
&lt;br /&gt;
==Resources== &amp;lt;!--T:21--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:22--&amp;gt;&lt;br /&gt;
This tab lets you manage files (pictures, media files) that were uploaded in the HTML Editor and it is only visible if you edit a survey - not during survey creation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:23--&amp;gt;&lt;br /&gt;
You can:&lt;br /&gt;
* Browse available files&lt;br /&gt;
* Export files as a ZIP archive&lt;br /&gt;
* Import a ZIP archive of files&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:24--&amp;gt;&lt;br /&gt;
Important hints:&lt;br /&gt;
* Authorized files extensions are defined in config-defaults.php.&lt;br /&gt;
* Files for the survey are in the upload/surveys/&amp;lt;sid&amp;gt; subdirectory.&lt;br /&gt;
* Uploaded files will only been seen while browsing resources on this survey (groups, questions, answers) not in other surveys or objects (labels).&lt;br /&gt;
* Do not expect this limited visibility to ensure confidentiality of the resources as they are reachable with a simple browser to anyone who know the URL to the file.&lt;br /&gt;
* You can&#039;t import a ZIP file containing subdirectories.&lt;br /&gt;
&lt;br /&gt;
=Additional languages= &amp;lt;!--T:25--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:26--&amp;gt;&lt;br /&gt;
To add more languages to a survey you have to create and save it - then edit it again. Now you can add and remove additional languages to the survey. If you remove a language from a survey the complete contents of that language in that survey is deleted permanently so be careful what you are doing.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:27--&amp;gt;&lt;br /&gt;
By clicking on the button &#039;Save and continue&#039; on the first page in the survey settings you will be taken to the language-specific page which lets you change all texts for each language like &#039;&#039;Survey name&#039;&#039;, &#039;&#039;Welcome Text&#039;&#039;, etc. You can also edit the date format which should be used for a certain language.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/translate&amp;gt;&lt;/div&gt;</summary>
		<author><name>LimeAJ</name></author>
	</entry>
	<entry>
		<id>https://www.limesurvey.org/manual/index.php?title=RemoteControl_2_API&amp;diff=76499</id>
		<title>RemoteControl 2 API</title>
		<link rel="alternate" type="text/html" href="https://www.limesurvey.org/manual/index.php?title=RemoteControl_2_API&amp;diff=76499"/>
		<updated>2017-08-29T18:02:07Z</updated>

		<summary type="html">&lt;p&gt;LimeAJ: /* PHP Example */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
=Introduction=&lt;br /&gt;
&lt;br /&gt;
LimeSurvey RemoteControl 2 is a XML-RPC/JSON-RPC based web service available in LimeSurvey 2.0 or more recent which offers &#039;&#039;&#039;various [https://api.limesurvey.org/classes/remotecontrol_handle.html API functions]&#039;&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
LSRC2 makes it possible for developers to control specific functionality of LimeSurvey from any other application, without being restricted to PHP as a programming language.&lt;br /&gt;
&lt;br /&gt;
The following features are planned:&lt;br /&gt;
* start a predefined survey (change titles and things)&lt;br /&gt;
* add predefined groups or questions&lt;br /&gt;
* activate the survey, restrict it to start and endtime&lt;br /&gt;
* make it closed,&lt;br /&gt;
* add participant data/tokens when you need them&lt;br /&gt;
* return the unused tokens to the main application&lt;br /&gt;
* get a fieldmap for a survey,&lt;br /&gt;
* invite or remind the participants of your survey&lt;br /&gt;
&lt;br /&gt;
...and much more&lt;br /&gt;
&lt;br /&gt;
==Requirements==&lt;br /&gt;
* libXML installed&lt;br /&gt;
&lt;br /&gt;
=Setup=&lt;br /&gt;
&lt;br /&gt;
== How to configure LSRC2==&lt;br /&gt;
&lt;br /&gt;
In a default LimeSurvey installation LSRC2 is disabled. In order to use LSRC2 you must first enable the service, and then adjust the settings to suit your needs. To enable LSRC2 login to the LimeSurvey administration, go to [[Global settings]], choose the tab &#039;Interfaces&#039; and select one of the two RPC services (XML-RPC or JSON-RPC) service.&lt;br /&gt;
&lt;br /&gt;
== Security==&lt;br /&gt;
&lt;br /&gt;
LSRC2 uses the same security measures as the normal administration login. That means that the permission set of the used username and password is the same as if you would login in the administration with that user/password. Also LSRC2 is protected against brute-force password cracking - like the normal administration login.&lt;br /&gt;
&lt;br /&gt;
=How to use LSRC2=&lt;br /&gt;
&lt;br /&gt;
The basic LSRC2 URL is: http://&amp;lt;your_domain&amp;gt;/&amp;lt;your_limesurvey_dir&amp;gt;/index.php/admin/remotecontrol&lt;br /&gt;
&lt;br /&gt;
LSRC2 fully complies to the [http://www.xmlrpc.com/ XML-RPC specification] and JSON-RPC version 1 specifications. We recommend in general to use JSON-RPC because it is well tested and has a much smaller footprint than XML-RPC.&lt;br /&gt;
&lt;br /&gt;
LSRC2 offers a lot of functions. Please check the automatically generated [http://api.limesurvey.org/classes/remotecontrol_handle.html API Documentation].&lt;br /&gt;
LSRC2 offers the following functions:&lt;br /&gt;
&lt;br /&gt;
== Sessions ==&lt;br /&gt;
&lt;br /&gt;
=== get_session_key ===&lt;br /&gt;
&lt;br /&gt;
Using this function you can create a new XML/JSON-RPC session key. This is mandatory for all following LSRC2 function calls.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=php&amp;gt;&lt;br /&gt;
function get_session_key(string $username, string $password)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Return on success&#039;&#039;&#039;: (string) session key.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Return on error&#039;&#039;&#039;:  for protocol-level errors (invalid format etc), an error message. For invalid username and password, returns a null error and the result body contains a &#039;status&#039; name-value pair with the error message.&lt;br /&gt;
&lt;br /&gt;
=== release_session_key ===&lt;br /&gt;
&lt;br /&gt;
Using this function you can close a previously opened XML-RPC/JSON-RPC session.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=php&amp;gt;&lt;br /&gt;
function release_session_key(string $sSessionKey)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Parameter !! Description&lt;br /&gt;
|-&lt;br /&gt;
| sSessionKey || Auth credentials&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Return&#039;&#039;&#039;: Always &#039;OK&#039; (string)&lt;br /&gt;
&lt;br /&gt;
== Other functions ==&lt;br /&gt;
&lt;br /&gt;
{{Alert|For all other function , you have to refer to the [http://api.limesurvey.org/classes/remotecontrol_handle.html online API ] . If your LimeSurvey version is outdated, you can publish your API and look at it directly.}}&lt;br /&gt;
&lt;br /&gt;
= Example and helper =&lt;br /&gt;
&lt;br /&gt;
== PHP Example ==&lt;br /&gt;
&lt;br /&gt;
To include JSON-RPC in your application, you can write an application using the light-weight jsonRPCClient from the [https://github.com/weberhofer/jsonrpcphp jsonrpcphp Github repository]. The library can also get included [https://getcomposer.org/download/ by composer calling]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
composer require weberhofer/jsonrpcphp&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or by inclusion of the following lines in your composer.json file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=javascript&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;require&amp;quot;: {&lt;br /&gt;
        &amp;quot;weberhofer/jsonrpcphp&amp;quot;: &amp;quot;~2&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is an example how to connect to limesurvey:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
// without composer this line can be used&lt;br /&gt;
// require_once &#039;path/to/your/rpcclient/jsonRPCClient.php&#039;;&lt;br /&gt;
// with composer support just add the autoloader&lt;br /&gt;
include_once &#039;vendor/autoload.php&#039;;&lt;br /&gt;
&lt;br /&gt;
define( &#039;LS_BASEURL&#039;, &#039;https://localhost/limesurvey/&#039;);  // adjust this one to your actual LimeSurvey URL&lt;br /&gt;
define( &#039;LS_USER&#039;, &#039;rpcuser&#039; );&lt;br /&gt;
define( &#039;LS_PASSWORD&#039;, &#039;mypassword&#039; );&lt;br /&gt;
&lt;br /&gt;
// the survey to process&lt;br /&gt;
$survey_id=374699;&lt;br /&gt;
&lt;br /&gt;
// instantiate a new client&lt;br /&gt;
$myJSONRPCClient = new \org\jsonrpcphp\JsonRPCClient( LS_BASEURL.&#039;/admin/remotecontrol&#039; );&lt;br /&gt;
&lt;br /&gt;
// receive session key&lt;br /&gt;
$sessionKey= $myJSONRPCClient-&amp;gt;get_session_key( LS_USER, LS_PASSWORD );&lt;br /&gt;
&lt;br /&gt;
// receive all ids and info of groups belonging to a given survey&lt;br /&gt;
$groups = $myJSONRPCClient-&amp;gt;list_groups( $sessionKey, $survey_id );&lt;br /&gt;
print_r($groups, null );&lt;br /&gt;
&lt;br /&gt;
// release the session key&lt;br /&gt;
$myJSONRPCClient-&amp;gt;release_session_key( $sessionKey );&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== JAVA example ==&lt;br /&gt;
To decode and code your json calls you can use the library gson as you can see in the following example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
import java.io.IOException;&lt;br /&gt;
import java.io.UnsupportedEncodingException;&lt;br /&gt;
&lt;br /&gt;
import org.apache.http.HttpEntity;&lt;br /&gt;
import org.apache.http.HttpResponse;&lt;br /&gt;
import org.apache.http.client.methods.HttpPost;&lt;br /&gt;
import org.apache.http.entity.StringEntity;&lt;br /&gt;
import org.apache.http.impl.client.DefaultHttpClient;&lt;br /&gt;
import org.apache.http.util.EntityUtils;&lt;br /&gt;
&lt;br /&gt;
import com.google.gson.JsonElement;&lt;br /&gt;
import com.google.gson.JsonObject;&lt;br /&gt;
import com.google.gson.JsonParser;&lt;br /&gt;
&lt;br /&gt;
public class TestHttpClient {&lt;br /&gt;
	&lt;br /&gt;
    public static String parse(String jsonLine) {&lt;br /&gt;
	 JsonElement jelement = new JsonParser().parse(jsonLine);&lt;br /&gt;
	 JsonObject  jobject = jelement.getAsJsonObject();&lt;br /&gt;
	 String result = jobject.get(&amp;quot;result&amp;quot;).getAsString();&lt;br /&gt;
	 return result;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	&lt;br /&gt;
    public static void main(String[] args) throws UnsupportedEncodingException {&lt;br /&gt;
      DefaultHttpClient client = new DefaultHttpClient();          &lt;br /&gt;
         &lt;br /&gt;
      HttpPost post = new HttpPost(&amp;quot;https://PATH_OF_YOUR_SERVER/index.php/admin/remotecontrol&amp;quot;);&lt;br /&gt;
      post.setHeader(&amp;quot;Content-type&amp;quot;, &amp;quot;application/json&amp;quot;);&lt;br /&gt;
      post.setEntity( new StringEntity(&amp;quot;{\&amp;quot;method\&amp;quot;: \&amp;quot;get_session_key\&amp;quot;, \&amp;quot;params\&amp;quot;: [\&amp;quot;YOUR_USERNAME\&amp;quot;, \&amp;quot;YOUR_PASSWORD\&amp;quot; ], \&amp;quot;id\&amp;quot;: 1}&amp;quot;));&lt;br /&gt;
      try {&lt;br /&gt;
        HttpResponse response = client.execute(post);&lt;br /&gt;
        if(response.getStatusLine().getStatusCode() == 200){&lt;br /&gt;
            HttpEntity entity = response.getEntity();&lt;br /&gt;
            String sessionKey = parse(EntityUtils.toString(entity));&lt;br /&gt;
            post.setEntity( new StringEntity(&amp;quot;{\&amp;quot;method\&amp;quot;: \&amp;quot;list_groups\&amp;quot;, \&amp;quot;params\&amp;quot;: [ \&amp;quot;&amp;quot;+sessionKey+&amp;quot;\&amp;quot;, \&amp;quot;ID_SURVEY\&amp;quot; ], \&amp;quot;id\&amp;quot;: 1}&amp;quot;));&lt;br /&gt;
            response = client.execute(post);&lt;br /&gt;
            if(response.getStatusLine().getStatusCode() == 200){&lt;br /&gt;
                entity = response.getEntity();&lt;br /&gt;
                System.out.println(EntityUtils.toString(entity));&lt;br /&gt;
                }&lt;br /&gt;
           }&lt;br /&gt;
       &lt;br /&gt;
       &lt;br /&gt;
      } catch (IOException e) {&lt;br /&gt;
        e.printStackTrace();&lt;br /&gt;
      }&lt;br /&gt;
    }}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Python example and glue ==&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/TaiSHiNet/lime-py-api LimeSurvey API - Python 2 glue]&lt;br /&gt;
* [https://github.com/lindsay-stevens/limesurveyrc2api LimeSurvey API - Basic client library in Python 3]. Includes tests. Listed on Pypi: pip install limesurveyrc2api&lt;br /&gt;
&lt;br /&gt;
The following code runs with Python 2 and requires some adaptation to work with Python 3.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
import urllib&lt;br /&gt;
import urllib2&lt;br /&gt;
import json&lt;br /&gt;
import sys&lt;br /&gt;
# There is an generic json-rpc implemantation in Python but it dose not work for me in this case so I worte Some functions &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
        &lt;br /&gt;
def get_session_key():&lt;br /&gt;
    req = urllib2.Request(url=&#039;https://myurl/index.php/admin/remotecontrol&#039;,\&lt;br /&gt;
                          data=&#039;{\&amp;quot;method\&amp;quot;:\&amp;quot;get_session_key\&amp;quot;,\&amp;quot;params\&amp;quot;:[\&amp;quot;admin\&amp;quot;,\&amp;quot;mypassword\&amp;quot;],\&amp;quot;id\&amp;quot;:1}&#039;)&lt;br /&gt;
    req.add_header(&#039;content-type&#039;, &#039;application/json&#039;)&lt;br /&gt;
    req.add_header(&#039;connection&#039;, &#039;Keep-Alive&#039;)&lt;br /&gt;
    try:&lt;br /&gt;
        f = urllib2.urlopen(req)&lt;br /&gt;
        myretun = f.read()&lt;br /&gt;
        #print myretun&lt;br /&gt;
        j=json.loads(myretun)&lt;br /&gt;
        return j[&#039;result&#039;]&lt;br /&gt;
    except :&lt;br /&gt;
        e = sys.exc_info()[0]&lt;br /&gt;
        print ( &amp;quot;&amp;lt;p&amp;gt;Error: %s&amp;lt;/p&amp;gt;&amp;quot; % e )&lt;br /&gt;
		&lt;br /&gt;
def get_question_properties(skey,QuestionID):&lt;br /&gt;
    req = urllib2.Request(url=&#039;https://myurl/index.php/admin/remotecontrol&#039;,\&lt;br /&gt;
                          data=&#039;{\&amp;quot;method\&amp;quot;:\&amp;quot;get_question_properties\&amp;quot;,\&amp;quot;params\&amp;quot;:[\&amp;quot;&#039;+skey+&#039;\&amp;quot;,&#039;+QuestionID&lt;br /&gt;
                                    +&#039;,[\&amp;quot;gid\&amp;quot;,\&amp;quot;type\&amp;quot;,\&amp;quot;help\&amp;quot;,\&amp;quot;language\&amp;quot;,\&amp;quot;sid\&amp;quot;,\&amp;quot;question_order\&amp;quot;,\&amp;quot;question\&amp;quot;,\&amp;quot;subquestions\&amp;quot;]],\&amp;quot;id\&amp;quot;: 1}&#039;)&lt;br /&gt;
&lt;br /&gt;
    req.add_header(&#039;content-type&#039;, &#039;application/json&#039;)&lt;br /&gt;
    req.add_header(&#039;connection&#039;, &#039;Keep-Alive&#039;)&lt;br /&gt;
    try:&lt;br /&gt;
        f = urllib2.urlopen(req)&lt;br /&gt;
        myretun = f.read()&lt;br /&gt;
        #print myretun&lt;br /&gt;
        j=json.loads(myretun)&lt;br /&gt;
        return j[&#039;result&#039;]&lt;br /&gt;
    except :&lt;br /&gt;
        e = sys.exc_info()[0]&lt;br /&gt;
        print ( &amp;quot;&amp;lt;p&amp;gt;Error: %s&amp;lt;/p&amp;gt;&amp;quot; % e )&lt;br /&gt;
&lt;br /&gt;
		&lt;br /&gt;
def release_session_key(relkey):&lt;br /&gt;
    req = urllib2.Request(url=&#039;https://myurl/index.php/admin/remotecontrol&#039;,\&lt;br /&gt;
                          data=&#039;{\&amp;quot;method\&amp;quot;:\&amp;quot;release_session_key\&amp;quot;,\&amp;quot;params\&amp;quot;:[\&amp;quot;&#039;+relkey+&#039;\&amp;quot;],\&amp;quot;id\&amp;quot;:1}&#039;)&lt;br /&gt;
    req.add_header(&#039;content-type&#039;, &#039;application/json&#039;)&lt;br /&gt;
    req.add_header(&#039;connection&#039;, &#039;Keep-Alive&#039;)&lt;br /&gt;
    try:&lt;br /&gt;
        f = urllib2.urlopen(req)&lt;br /&gt;
        myretun = f.read()&lt;br /&gt;
        #print myretun&lt;br /&gt;
        j=json.loads(myretun)&lt;br /&gt;
        return j[&#039;result&#039;]&lt;br /&gt;
    except :&lt;br /&gt;
        e = sys.exc_info()[0]&lt;br /&gt;
        print ( &amp;quot;&amp;lt;p&amp;gt;Error: %s&amp;lt;/p&amp;gt;&amp;quot; % e )&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def export_responses2(skey,sid):&lt;br /&gt;
    req = urllib2.Request(url=&#039;https://myurl/index.php/admin/remotecontrol&#039;,\&lt;br /&gt;
                          data=&#039;{\&amp;quot;method\&amp;quot;:\&amp;quot;export_responses\&amp;quot;,\&amp;quot;params\&amp;quot;:[\&amp;quot;&#039;+skey+&#039;\&amp;quot;,\&amp;quot;&#039;+sid+&#039;\&amp;quot;,\&amp;quot;csv\&amp;quot;,\&amp;quot;de\&amp;quot;,\&amp;quot;full\&amp;quot;],\&lt;br /&gt;
&amp;quot;id\&amp;quot;: 1}&#039;)&lt;br /&gt;
    req.add_header(&#039;content-type&#039;, &#039;application/json&#039;)&lt;br /&gt;
    req.add_header(&#039;connection&#039;, &#039;Keep-Alive&#039;)&lt;br /&gt;
    try:&lt;br /&gt;
        f = urllib2.urlopen(req)&lt;br /&gt;
        myretun = f.read()&lt;br /&gt;
        #print myretun&lt;br /&gt;
        j=json.loads(myretun)&lt;br /&gt;
        return j[&#039;result&#039;]&lt;br /&gt;
    except :&lt;br /&gt;
        e = sys.exc_info()[0]&lt;br /&gt;
        print ( &amp;quot;&amp;lt;p&amp;gt;Error: %s&amp;lt;/p&amp;gt;&amp;quot; % e )		&lt;br /&gt;
&lt;br /&gt;
		&lt;br /&gt;
mykey=get_session_key()&lt;br /&gt;
print export_responses2(mykey,&#039;566237&#039;).decode(&#039;base64&#039;)&lt;br /&gt;
get_question_properties(mykey,&#039;574&#039;)&lt;br /&gt;
print release_session_key(mykey)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== NodeJS example ==&lt;br /&gt;
&lt;br /&gt;
This script require request, you can include easily with the command &lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
npm install request&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is a example how to connect to limesurvey:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
var request = require(&#039;request&#039;);&lt;br /&gt;
&lt;br /&gt;
//******GLOBAL***************&lt;br /&gt;
var SESSIONKEY=&amp;quot;&amp;quot;;&lt;br /&gt;
var options = {&lt;br /&gt;
  url: &amp;quot;https://xxxxxxxxxxxxxxxx/index.php/admin/remotecontrol&amp;quot;,&lt;br /&gt;
  method: &amp;quot;POST&amp;quot;,&lt;br /&gt;
  headers: {&lt;br /&gt;
    &#039;user-agent&#039;: &#039;Apache-HttpClient/4.2.2 (java 1.5)&#039;,&lt;br /&gt;
    &#039;host&#039;: &#039;xxxxxxxxxxxxxxxx&#039;,&lt;br /&gt;
    &#039;path&#039;: &#039;/index.php/admin/remotecontrol&#039;,&lt;br /&gt;
    &#039;connection&#039;: &#039;keep-alive&#039;,&lt;br /&gt;
    &#039;content-type&#039;: &#039;application/json&#039;&lt;br /&gt;
  }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
//*******AUTHENTIFICATION*******&lt;br /&gt;
options.body = JSON.stringify({method:&#039;get_session_key&#039;,params:[&#039;myusername&#039;,&#039;mypassword&#039;],id:1});&lt;br /&gt;
&lt;br /&gt;
request(options, function(error, response, body){&lt;br /&gt;
  if (!error &amp;amp;&amp;amp; response.statusCode == 200) {&lt;br /&gt;
      body = JSON.parse(body);&lt;br /&gt;
&lt;br /&gt;
    //*********KEEP THE KEY*********  &lt;br /&gt;
    if(SESSIONKEY===&amp;quot;&amp;quot;) {&lt;br /&gt;
      console.log(&amp;quot;NEW KEY --&amp;gt;&amp;quot;+body.result);&lt;br /&gt;
      SESSIONKEY=body.result;&lt;br /&gt;
      nextFonction();&lt;br /&gt;
    } &lt;br /&gt;
  }&lt;br /&gt;
  else console.log(&amp;quot;ERROR --&amp;gt;&amp;quot;+body);  &lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== R example and helper ==&lt;br /&gt;
&lt;br /&gt;
The easiest way to use lsrc2 is by means of the limer package, See https://github.com/cloudyr/limer&lt;br /&gt;
&lt;br /&gt;
Example of usage of this client&lt;br /&gt;
&amp;lt;source lang=R&amp;gt;&lt;br /&gt;
# first limer (check version: must be recent) must be installed&lt;br /&gt;
if(!require(&amp;quot;devtools&amp;quot;)) {&lt;br /&gt;
  install.packages(&amp;quot;devtools&amp;quot;)&lt;br /&gt;
  library(&amp;quot;devtools&amp;quot;)&lt;br /&gt;
}&lt;br /&gt;
install_github(&amp;quot;cloudyr/limer&amp;quot;)&lt;br /&gt;
#############################################################&lt;br /&gt;
&lt;br /&gt;
library(limer)&lt;br /&gt;
&lt;br /&gt;
#change the next options (website, user, password)&lt;br /&gt;
options&lt;br /&gt;
(lime_api = &#039;https://www.XXX.nl/index.php/admin/remotecontrol&#039;)&lt;br /&gt;
options(lime_username = &#039;user&#039;)&lt;br /&gt;
options(lime_password = &#039;password&#039;)&lt;br /&gt;
#############################################################&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# first get a session access key&lt;br /&gt;
get_session_key()&lt;br /&gt;
&lt;br /&gt;
# list all surveys. A dataframe is returned&lt;br /&gt;
survey_df&amp;lt;-call_limer(method=&#039;list_surveys&#039;)&lt;br /&gt;
print(survey_df)&lt;br /&gt;
#    sid           surveyls_title startdate             expires active&lt;br /&gt;
#1  999999  XXXX               NA 2016-03-08 15:20:30      Y&lt;br /&gt;
#2  999998  XXXX               NA   &amp;lt;NA&amp;gt;      Y&lt;br /&gt;
&lt;br /&gt;
#Read the data of the first survey (sid=999999) into a data.frame. &lt;br /&gt;
#Notice that the default sLanguageCode = en, so maybe you have to &lt;br /&gt;
#specify another language (here: All languages)&lt;br /&gt;
data&amp;lt;- get_responses(iSurveyID= 999999, sLanguageCode= &#039;&#039;, sResponseType=&#039;short&#039;)&lt;br /&gt;
        &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= JSON-RPC notes =&lt;br /&gt;
&lt;br /&gt;
The content-type of the HTTP request &#039;&#039;&#039;must be application/json&#039;&#039;&#039;.  Most formatting errors are a failure to set the content-type header.  This will result in a null response from the server (not a JSON response).  Below is an example of a valid request and response pair.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;Request:&lt;br /&gt;
&lt;br /&gt;
 HTTP headers:&lt;br /&gt;
&lt;br /&gt;
   content-type=application/json&lt;br /&gt;
&lt;br /&gt;
   connection=Keep-Alive&lt;br /&gt;
&lt;br /&gt;
   host=mylimesurveyhost.com&lt;br /&gt;
&lt;br /&gt;
   content-length=67&lt;br /&gt;
&lt;br /&gt;
   user-agent=Apache-HttpClient/4.2.2 (java 1.5)&lt;br /&gt;
&lt;br /&gt;
 Post body:&lt;br /&gt;
&lt;br /&gt;
   {&amp;quot;method&amp;quot;:&amp;quot;get_session_key&amp;quot;,&amp;quot;params&amp;quot;:[&amp;quot;admin&amp;quot;,&amp;quot;mypassword&amp;quot;],&amp;quot;id&amp;quot;:1}&lt;br /&gt;
&lt;br /&gt;
Response body:&lt;br /&gt;
&lt;br /&gt;
 {&amp;quot;id&amp;quot;:1,&amp;quot;result&amp;quot;:&amp;quot;6htqat38fyr4v7iu72nqgv7xgavkvfcz&amp;quot;,&amp;quot;error&amp;quot;:null}&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>LimeAJ</name></author>
	</entry>
	<entry>
		<id>https://www.limesurvey.org/manual/index.php?title=RemoteControl_2_API&amp;diff=76498</id>
		<title>RemoteControl 2 API</title>
		<link rel="alternate" type="text/html" href="https://www.limesurvey.org/manual/index.php?title=RemoteControl_2_API&amp;diff=76498"/>
		<updated>2017-08-29T14:25:44Z</updated>

		<summary type="html">&lt;p&gt;LimeAJ: /* JSON-RPC notes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
=Introduction=&lt;br /&gt;
&lt;br /&gt;
LimeSurvey RemoteControl 2 is a XML-RPC/JSON-RPC based web service available in LimeSurvey 2.0 or more recent which offers &#039;&#039;&#039;various [https://api.limesurvey.org/classes/remotecontrol_handle.html API functions]&#039;&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
LSRC2 makes it possible for developers to control specific functionality of LimeSurvey from any other application, without being restricted to PHP as a programming language.&lt;br /&gt;
&lt;br /&gt;
The following features are planned:&lt;br /&gt;
* start a predefined survey (change titles and things)&lt;br /&gt;
* add predefined groups or questions&lt;br /&gt;
* activate the survey, restrict it to start and endtime&lt;br /&gt;
* make it closed,&lt;br /&gt;
* add participant data/tokens when you need them&lt;br /&gt;
* return the unused tokens to the main application&lt;br /&gt;
* get a fieldmap for a survey,&lt;br /&gt;
* invite or remind the participants of your survey&lt;br /&gt;
&lt;br /&gt;
...and much more&lt;br /&gt;
&lt;br /&gt;
==Requirements==&lt;br /&gt;
* libXML installed&lt;br /&gt;
&lt;br /&gt;
=Setup=&lt;br /&gt;
&lt;br /&gt;
== How to configure LSRC2==&lt;br /&gt;
&lt;br /&gt;
In a default LimeSurvey installation LSRC2 is disabled. In order to use LSRC2 you must first enable the service, and then adjust the settings to suit your needs. To enable LSRC2 login to the LimeSurvey administration, go to [[Global settings]], choose the tab &#039;Interfaces&#039; and select one of the two RPC services (XML-RPC or JSON-RPC) service.&lt;br /&gt;
&lt;br /&gt;
== Security==&lt;br /&gt;
&lt;br /&gt;
LSRC2 uses the same security measures as the normal administration login. That means that the permission set of the used username and password is the same as if you would login in the administration with that user/password. Also LSRC2 is protected against brute-force password cracking - like the normal administration login.&lt;br /&gt;
&lt;br /&gt;
=How to use LSRC2=&lt;br /&gt;
&lt;br /&gt;
The basic LSRC2 URL is: http://&amp;lt;your_domain&amp;gt;/&amp;lt;your_limesurvey_dir&amp;gt;/index.php/admin/remotecontrol&lt;br /&gt;
&lt;br /&gt;
LSRC2 fully complies to the [http://www.xmlrpc.com/ XML-RPC specification] and JSON-RPC version 1 specifications. We recommend in general to use JSON-RPC because it is well tested and has a much smaller footprint than XML-RPC.&lt;br /&gt;
&lt;br /&gt;
LSRC2 offers a lot of functions. Please check the automatically generated [http://api.limesurvey.org/classes/remotecontrol_handle.html API Documentation].&lt;br /&gt;
LSRC2 offers the following functions:&lt;br /&gt;
&lt;br /&gt;
== Sessions ==&lt;br /&gt;
&lt;br /&gt;
=== get_session_key ===&lt;br /&gt;
&lt;br /&gt;
Using this function you can create a new XML/JSON-RPC session key. This is mandatory for all following LSRC2 function calls.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=php&amp;gt;&lt;br /&gt;
function get_session_key(string $username, string $password)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Return on success&#039;&#039;&#039;: (string) session key.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Return on error&#039;&#039;&#039;:  for protocol-level errors (invalid format etc), an error message. For invalid username and password, returns a null error and the result body contains a &#039;status&#039; name-value pair with the error message.&lt;br /&gt;
&lt;br /&gt;
=== release_session_key ===&lt;br /&gt;
&lt;br /&gt;
Using this function you can close a previously opened XML-RPC/JSON-RPC session.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=php&amp;gt;&lt;br /&gt;
function release_session_key(string $sSessionKey)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Parameter !! Description&lt;br /&gt;
|-&lt;br /&gt;
| sSessionKey || Auth credentials&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Return&#039;&#039;&#039;: Always &#039;OK&#039; (string)&lt;br /&gt;
&lt;br /&gt;
== Other functions ==&lt;br /&gt;
&lt;br /&gt;
{{Alert|For all other function , you have to refer to the [http://api.limesurvey.org/classes/remotecontrol_handle.html online API ] . If your LimeSurvey version is outdated, you can publish your API and look at it directly.}}&lt;br /&gt;
&lt;br /&gt;
= Example and helper =&lt;br /&gt;
&lt;br /&gt;
== PHP Example ==&lt;br /&gt;
&lt;br /&gt;
To include JSON-RPC in your application, you can write an application using the light-weight jsonRPCClient from the [https://github.com/weberhofer/jsonrpcphp jsonrpcphp Github repository]. The library can also get included [https://getcomposer.org/download/ by composer calling]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
composer require weberhofer/jsonrpcphp&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or by inclusion of the following lines in your composer.json file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=javascript&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;require&amp;quot;: {&lt;br /&gt;
        &amp;quot;weberhofer/jsonrpcphp&amp;quot;: &amp;quot;~2&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is a example how to connect to limesurvey:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
// without composer this line can be used&lt;br /&gt;
// require_once &#039;path/to/your/rpcclient/jsonRPCClient.php&#039;;&lt;br /&gt;
// with composer support just add the autoloader&lt;br /&gt;
include_once &#039;vendor/autoload.php&#039;;&lt;br /&gt;
&lt;br /&gt;
define( &#039;LS_BASEURL&#039;, &#039;https://localhost/limesurvey/&#039;);  // adjust this one to your actual LimeSurvey URL&lt;br /&gt;
define( &#039;LS_USER&#039;, &#039;rpcuser&#039; );&lt;br /&gt;
define( &#039;LS_PASSWORD&#039;, &#039;mypassword&#039; );&lt;br /&gt;
&lt;br /&gt;
// the survey to process&lt;br /&gt;
$survey_id=374699;&lt;br /&gt;
&lt;br /&gt;
// instantiate a new client&lt;br /&gt;
$myJSONRPCClient = new \org\jsonrpcphp\JsonRPCClient( LS_BASEURL.&#039;/admin/remotecontrol&#039; );&lt;br /&gt;
&lt;br /&gt;
// receive session key&lt;br /&gt;
$sessionKey= $myJSONRPCClient-&amp;gt;get_session_key( LS_USER, LS_PASSWORD );&lt;br /&gt;
&lt;br /&gt;
// receive all ids and info of groups belonging to a given survey&lt;br /&gt;
$groups = $myJSONRPCClient-&amp;gt;list_groups( $sessionKey, $survey_id );&lt;br /&gt;
print_r($groups, null );&lt;br /&gt;
&lt;br /&gt;
// release the session key&lt;br /&gt;
$myJSONRPCClient-&amp;gt;release_session_key( $sessionKey );&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== JAVA example ==&lt;br /&gt;
To decode and code your json calls you can use the library gson as you can see in the following example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
import java.io.IOException;&lt;br /&gt;
import java.io.UnsupportedEncodingException;&lt;br /&gt;
&lt;br /&gt;
import org.apache.http.HttpEntity;&lt;br /&gt;
import org.apache.http.HttpResponse;&lt;br /&gt;
import org.apache.http.client.methods.HttpPost;&lt;br /&gt;
import org.apache.http.entity.StringEntity;&lt;br /&gt;
import org.apache.http.impl.client.DefaultHttpClient;&lt;br /&gt;
import org.apache.http.util.EntityUtils;&lt;br /&gt;
&lt;br /&gt;
import com.google.gson.JsonElement;&lt;br /&gt;
import com.google.gson.JsonObject;&lt;br /&gt;
import com.google.gson.JsonParser;&lt;br /&gt;
&lt;br /&gt;
public class TestHttpClient {&lt;br /&gt;
	&lt;br /&gt;
    public static String parse(String jsonLine) {&lt;br /&gt;
	 JsonElement jelement = new JsonParser().parse(jsonLine);&lt;br /&gt;
	 JsonObject  jobject = jelement.getAsJsonObject();&lt;br /&gt;
	 String result = jobject.get(&amp;quot;result&amp;quot;).getAsString();&lt;br /&gt;
	 return result;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	&lt;br /&gt;
    public static void main(String[] args) throws UnsupportedEncodingException {&lt;br /&gt;
      DefaultHttpClient client = new DefaultHttpClient();          &lt;br /&gt;
         &lt;br /&gt;
      HttpPost post = new HttpPost(&amp;quot;https://PATH_OF_YOUR_SERVER/index.php/admin/remotecontrol&amp;quot;);&lt;br /&gt;
      post.setHeader(&amp;quot;Content-type&amp;quot;, &amp;quot;application/json&amp;quot;);&lt;br /&gt;
      post.setEntity( new StringEntity(&amp;quot;{\&amp;quot;method\&amp;quot;: \&amp;quot;get_session_key\&amp;quot;, \&amp;quot;params\&amp;quot;: [\&amp;quot;YOUR_USERNAME\&amp;quot;, \&amp;quot;YOUR_PASSWORD\&amp;quot; ], \&amp;quot;id\&amp;quot;: 1}&amp;quot;));&lt;br /&gt;
      try {&lt;br /&gt;
        HttpResponse response = client.execute(post);&lt;br /&gt;
        if(response.getStatusLine().getStatusCode() == 200){&lt;br /&gt;
            HttpEntity entity = response.getEntity();&lt;br /&gt;
            String sessionKey = parse(EntityUtils.toString(entity));&lt;br /&gt;
            post.setEntity( new StringEntity(&amp;quot;{\&amp;quot;method\&amp;quot;: \&amp;quot;list_groups\&amp;quot;, \&amp;quot;params\&amp;quot;: [ \&amp;quot;&amp;quot;+sessionKey+&amp;quot;\&amp;quot;, \&amp;quot;ID_SURVEY\&amp;quot; ], \&amp;quot;id\&amp;quot;: 1}&amp;quot;));&lt;br /&gt;
            response = client.execute(post);&lt;br /&gt;
            if(response.getStatusLine().getStatusCode() == 200){&lt;br /&gt;
                entity = response.getEntity();&lt;br /&gt;
                System.out.println(EntityUtils.toString(entity));&lt;br /&gt;
                }&lt;br /&gt;
           }&lt;br /&gt;
       &lt;br /&gt;
       &lt;br /&gt;
      } catch (IOException e) {&lt;br /&gt;
        e.printStackTrace();&lt;br /&gt;
      }&lt;br /&gt;
    }}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Python example and glue ==&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/TaiSHiNet/lime-py-api LimeSurvey API - Python 2 glue]&lt;br /&gt;
* [https://github.com/lindsay-stevens/limesurveyrc2api LimeSurvey API - Basic client library in Python 3]. Includes tests. Listed on Pypi: pip install limesurveyrc2api&lt;br /&gt;
&lt;br /&gt;
The following code runs with Python 2 and requires some adaptation to work with Python 3.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
import urllib&lt;br /&gt;
import urllib2&lt;br /&gt;
import json&lt;br /&gt;
import sys&lt;br /&gt;
# There is an generic json-rpc implemantation in Python but it dose not work for me in this case so I worte Some functions &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
        &lt;br /&gt;
def get_session_key():&lt;br /&gt;
    req = urllib2.Request(url=&#039;https://myurl/index.php/admin/remotecontrol&#039;,\&lt;br /&gt;
                          data=&#039;{\&amp;quot;method\&amp;quot;:\&amp;quot;get_session_key\&amp;quot;,\&amp;quot;params\&amp;quot;:[\&amp;quot;admin\&amp;quot;,\&amp;quot;mypassword\&amp;quot;],\&amp;quot;id\&amp;quot;:1}&#039;)&lt;br /&gt;
    req.add_header(&#039;content-type&#039;, &#039;application/json&#039;)&lt;br /&gt;
    req.add_header(&#039;connection&#039;, &#039;Keep-Alive&#039;)&lt;br /&gt;
    try:&lt;br /&gt;
        f = urllib2.urlopen(req)&lt;br /&gt;
        myretun = f.read()&lt;br /&gt;
        #print myretun&lt;br /&gt;
        j=json.loads(myretun)&lt;br /&gt;
        return j[&#039;result&#039;]&lt;br /&gt;
    except :&lt;br /&gt;
        e = sys.exc_info()[0]&lt;br /&gt;
        print ( &amp;quot;&amp;lt;p&amp;gt;Error: %s&amp;lt;/p&amp;gt;&amp;quot; % e )&lt;br /&gt;
		&lt;br /&gt;
def get_question_properties(skey,QuestionID):&lt;br /&gt;
    req = urllib2.Request(url=&#039;https://myurl/index.php/admin/remotecontrol&#039;,\&lt;br /&gt;
                          data=&#039;{\&amp;quot;method\&amp;quot;:\&amp;quot;get_question_properties\&amp;quot;,\&amp;quot;params\&amp;quot;:[\&amp;quot;&#039;+skey+&#039;\&amp;quot;,&#039;+QuestionID&lt;br /&gt;
                                    +&#039;,[\&amp;quot;gid\&amp;quot;,\&amp;quot;type\&amp;quot;,\&amp;quot;help\&amp;quot;,\&amp;quot;language\&amp;quot;,\&amp;quot;sid\&amp;quot;,\&amp;quot;question_order\&amp;quot;,\&amp;quot;question\&amp;quot;,\&amp;quot;subquestions\&amp;quot;]],\&amp;quot;id\&amp;quot;: 1}&#039;)&lt;br /&gt;
&lt;br /&gt;
    req.add_header(&#039;content-type&#039;, &#039;application/json&#039;)&lt;br /&gt;
    req.add_header(&#039;connection&#039;, &#039;Keep-Alive&#039;)&lt;br /&gt;
    try:&lt;br /&gt;
        f = urllib2.urlopen(req)&lt;br /&gt;
        myretun = f.read()&lt;br /&gt;
        #print myretun&lt;br /&gt;
        j=json.loads(myretun)&lt;br /&gt;
        return j[&#039;result&#039;]&lt;br /&gt;
    except :&lt;br /&gt;
        e = sys.exc_info()[0]&lt;br /&gt;
        print ( &amp;quot;&amp;lt;p&amp;gt;Error: %s&amp;lt;/p&amp;gt;&amp;quot; % e )&lt;br /&gt;
&lt;br /&gt;
		&lt;br /&gt;
def release_session_key(relkey):&lt;br /&gt;
    req = urllib2.Request(url=&#039;https://myurl/index.php/admin/remotecontrol&#039;,\&lt;br /&gt;
                          data=&#039;{\&amp;quot;method\&amp;quot;:\&amp;quot;release_session_key\&amp;quot;,\&amp;quot;params\&amp;quot;:[\&amp;quot;&#039;+relkey+&#039;\&amp;quot;],\&amp;quot;id\&amp;quot;:1}&#039;)&lt;br /&gt;
    req.add_header(&#039;content-type&#039;, &#039;application/json&#039;)&lt;br /&gt;
    req.add_header(&#039;connection&#039;, &#039;Keep-Alive&#039;)&lt;br /&gt;
    try:&lt;br /&gt;
        f = urllib2.urlopen(req)&lt;br /&gt;
        myretun = f.read()&lt;br /&gt;
        #print myretun&lt;br /&gt;
        j=json.loads(myretun)&lt;br /&gt;
        return j[&#039;result&#039;]&lt;br /&gt;
    except :&lt;br /&gt;
        e = sys.exc_info()[0]&lt;br /&gt;
        print ( &amp;quot;&amp;lt;p&amp;gt;Error: %s&amp;lt;/p&amp;gt;&amp;quot; % e )&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def export_responses2(skey,sid):&lt;br /&gt;
    req = urllib2.Request(url=&#039;https://myurl/index.php/admin/remotecontrol&#039;,\&lt;br /&gt;
                          data=&#039;{\&amp;quot;method\&amp;quot;:\&amp;quot;export_responses\&amp;quot;,\&amp;quot;params\&amp;quot;:[\&amp;quot;&#039;+skey+&#039;\&amp;quot;,\&amp;quot;&#039;+sid+&#039;\&amp;quot;,\&amp;quot;csv\&amp;quot;,\&amp;quot;de\&amp;quot;,\&amp;quot;full\&amp;quot;],\&lt;br /&gt;
&amp;quot;id\&amp;quot;: 1}&#039;)&lt;br /&gt;
    req.add_header(&#039;content-type&#039;, &#039;application/json&#039;)&lt;br /&gt;
    req.add_header(&#039;connection&#039;, &#039;Keep-Alive&#039;)&lt;br /&gt;
    try:&lt;br /&gt;
        f = urllib2.urlopen(req)&lt;br /&gt;
        myretun = f.read()&lt;br /&gt;
        #print myretun&lt;br /&gt;
        j=json.loads(myretun)&lt;br /&gt;
        return j[&#039;result&#039;]&lt;br /&gt;
    except :&lt;br /&gt;
        e = sys.exc_info()[0]&lt;br /&gt;
        print ( &amp;quot;&amp;lt;p&amp;gt;Error: %s&amp;lt;/p&amp;gt;&amp;quot; % e )		&lt;br /&gt;
&lt;br /&gt;
		&lt;br /&gt;
mykey=get_session_key()&lt;br /&gt;
print export_responses2(mykey,&#039;566237&#039;).decode(&#039;base64&#039;)&lt;br /&gt;
get_question_properties(mykey,&#039;574&#039;)&lt;br /&gt;
print release_session_key(mykey)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== NodeJS example ==&lt;br /&gt;
&lt;br /&gt;
This script require request, you can include easily with the command &lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
npm install request&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is a example how to connect to limesurvey:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
var request = require(&#039;request&#039;);&lt;br /&gt;
&lt;br /&gt;
//******GLOBAL***************&lt;br /&gt;
var SESSIONKEY=&amp;quot;&amp;quot;;&lt;br /&gt;
var options = {&lt;br /&gt;
  url: &amp;quot;https://xxxxxxxxxxxxxxxx/index.php/admin/remotecontrol&amp;quot;,&lt;br /&gt;
  method: &amp;quot;POST&amp;quot;,&lt;br /&gt;
  headers: {&lt;br /&gt;
    &#039;user-agent&#039;: &#039;Apache-HttpClient/4.2.2 (java 1.5)&#039;,&lt;br /&gt;
    &#039;host&#039;: &#039;xxxxxxxxxxxxxxxx&#039;,&lt;br /&gt;
    &#039;path&#039;: &#039;/index.php/admin/remotecontrol&#039;,&lt;br /&gt;
    &#039;connection&#039;: &#039;keep-alive&#039;,&lt;br /&gt;
    &#039;content-type&#039;: &#039;application/json&#039;&lt;br /&gt;
  }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
//*******AUTHENTIFICATION*******&lt;br /&gt;
options.body = JSON.stringify({method:&#039;get_session_key&#039;,params:[&#039;myusername&#039;,&#039;mypassword&#039;],id:1});&lt;br /&gt;
&lt;br /&gt;
request(options, function(error, response, body){&lt;br /&gt;
  if (!error &amp;amp;&amp;amp; response.statusCode == 200) {&lt;br /&gt;
      body = JSON.parse(body);&lt;br /&gt;
&lt;br /&gt;
    //*********KEEP THE KEY*********  &lt;br /&gt;
    if(SESSIONKEY===&amp;quot;&amp;quot;) {&lt;br /&gt;
      console.log(&amp;quot;NEW KEY --&amp;gt;&amp;quot;+body.result);&lt;br /&gt;
      SESSIONKEY=body.result;&lt;br /&gt;
      nextFonction();&lt;br /&gt;
    } &lt;br /&gt;
  }&lt;br /&gt;
  else console.log(&amp;quot;ERROR --&amp;gt;&amp;quot;+body);  &lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== R example and helper ==&lt;br /&gt;
&lt;br /&gt;
The easiest way to use lsrc2 is by means of the limer package, See https://github.com/cloudyr/limer&lt;br /&gt;
&lt;br /&gt;
Example of usage of this client&lt;br /&gt;
&amp;lt;source lang=R&amp;gt;&lt;br /&gt;
# first limer (check version: must be recent) must be installed&lt;br /&gt;
if(!require(&amp;quot;devtools&amp;quot;)) {&lt;br /&gt;
  install.packages(&amp;quot;devtools&amp;quot;)&lt;br /&gt;
  library(&amp;quot;devtools&amp;quot;)&lt;br /&gt;
}&lt;br /&gt;
install_github(&amp;quot;cloudyr/limer&amp;quot;)&lt;br /&gt;
#############################################################&lt;br /&gt;
&lt;br /&gt;
library(limer)&lt;br /&gt;
&lt;br /&gt;
#change the next options (website, user, password)&lt;br /&gt;
options&lt;br /&gt;
(lime_api = &#039;https://www.XXX.nl/index.php/admin/remotecontrol&#039;)&lt;br /&gt;
options(lime_username = &#039;user&#039;)&lt;br /&gt;
options(lime_password = &#039;password&#039;)&lt;br /&gt;
#############################################################&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# first get a session access key&lt;br /&gt;
get_session_key()&lt;br /&gt;
&lt;br /&gt;
# list all surveys. A dataframe is returned&lt;br /&gt;
survey_df&amp;lt;-call_limer(method=&#039;list_surveys&#039;)&lt;br /&gt;
print(survey_df)&lt;br /&gt;
#    sid           surveyls_title startdate             expires active&lt;br /&gt;
#1  999999  XXXX               NA 2016-03-08 15:20:30      Y&lt;br /&gt;
#2  999998  XXXX               NA   &amp;lt;NA&amp;gt;      Y&lt;br /&gt;
&lt;br /&gt;
#Read the data of the first survey (sid=999999) into a data.frame. &lt;br /&gt;
#Notice that the default sLanguageCode = en, so maybe you have to &lt;br /&gt;
#specify another language (here: All languages)&lt;br /&gt;
data&amp;lt;- get_responses(iSurveyID= 999999, sLanguageCode= &#039;&#039;, sResponseType=&#039;short&#039;)&lt;br /&gt;
        &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= JSON-RPC notes =&lt;br /&gt;
&lt;br /&gt;
The content-type of the HTTP request &#039;&#039;&#039;must be application/json&#039;&#039;&#039;.  Most formatting errors are a failure to set the content-type header.  This will result in a null response from the server (not a JSON response).  Below is an example of a valid request and response pair.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;Request:&lt;br /&gt;
&lt;br /&gt;
 HTTP headers:&lt;br /&gt;
&lt;br /&gt;
   content-type=application/json&lt;br /&gt;
&lt;br /&gt;
   connection=Keep-Alive&lt;br /&gt;
&lt;br /&gt;
   host=mylimesurveyhost.com&lt;br /&gt;
&lt;br /&gt;
   content-length=67&lt;br /&gt;
&lt;br /&gt;
   user-agent=Apache-HttpClient/4.2.2 (java 1.5)&lt;br /&gt;
&lt;br /&gt;
 Post body:&lt;br /&gt;
&lt;br /&gt;
   {&amp;quot;method&amp;quot;:&amp;quot;get_session_key&amp;quot;,&amp;quot;params&amp;quot;:[&amp;quot;admin&amp;quot;,&amp;quot;mypassword&amp;quot;],&amp;quot;id&amp;quot;:1}&lt;br /&gt;
&lt;br /&gt;
Response body:&lt;br /&gt;
&lt;br /&gt;
 {&amp;quot;id&amp;quot;:1,&amp;quot;result&amp;quot;:&amp;quot;6htqat38fyr4v7iu72nqgv7xgavkvfcz&amp;quot;,&amp;quot;error&amp;quot;:null}&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>LimeAJ</name></author>
	</entry>
	<entry>
		<id>https://www.limesurvey.org/manual/index.php?title=RemoteControl_2_API&amp;diff=76497</id>
		<title>RemoteControl 2 API</title>
		<link rel="alternate" type="text/html" href="https://www.limesurvey.org/manual/index.php?title=RemoteControl_2_API&amp;diff=76497"/>
		<updated>2017-08-29T14:22:41Z</updated>

		<summary type="html">&lt;p&gt;LimeAJ: /* JSON-RPC notes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
=Introduction=&lt;br /&gt;
&lt;br /&gt;
LimeSurvey RemoteControl 2 is a XML-RPC/JSON-RPC based web service available in LimeSurvey 2.0 or more recent which offers &#039;&#039;&#039;various [https://api.limesurvey.org/classes/remotecontrol_handle.html API functions]&#039;&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
LSRC2 makes it possible for developers to control specific functionality of LimeSurvey from any other application, without being restricted to PHP as a programming language.&lt;br /&gt;
&lt;br /&gt;
The following features are planned:&lt;br /&gt;
* start a predefined survey (change titles and things)&lt;br /&gt;
* add predefined groups or questions&lt;br /&gt;
* activate the survey, restrict it to start and endtime&lt;br /&gt;
* make it closed,&lt;br /&gt;
* add participant data/tokens when you need them&lt;br /&gt;
* return the unused tokens to the main application&lt;br /&gt;
* get a fieldmap for a survey,&lt;br /&gt;
* invite or remind the participants of your survey&lt;br /&gt;
&lt;br /&gt;
...and much more&lt;br /&gt;
&lt;br /&gt;
==Requirements==&lt;br /&gt;
* libXML installed&lt;br /&gt;
&lt;br /&gt;
=Setup=&lt;br /&gt;
&lt;br /&gt;
== How to configure LSRC2==&lt;br /&gt;
&lt;br /&gt;
In a default LimeSurvey installation LSRC2 is disabled. In order to use LSRC2 you must first enable the service, and then adjust the settings to suit your needs. To enable LSRC2 login to the LimeSurvey administration, go to [[Global settings]], choose the tab &#039;Interfaces&#039; and select one of the two RPC services (XML-RPC or JSON-RPC) service.&lt;br /&gt;
&lt;br /&gt;
== Security==&lt;br /&gt;
&lt;br /&gt;
LSRC2 uses the same security measures as the normal administration login. That means that the permission set of the used username and password is the same as if you would login in the administration with that user/password. Also LSRC2 is protected against brute-force password cracking - like the normal administration login.&lt;br /&gt;
&lt;br /&gt;
=How to use LSRC2=&lt;br /&gt;
&lt;br /&gt;
The basic LSRC2 URL is: http://&amp;lt;your_domain&amp;gt;/&amp;lt;your_limesurvey_dir&amp;gt;/index.php/admin/remotecontrol&lt;br /&gt;
&lt;br /&gt;
LSRC2 fully complies to the [http://www.xmlrpc.com/ XML-RPC specification] and JSON-RPC version 1 specifications. We recommend in general to use JSON-RPC because it is well tested and has a much smaller footprint than XML-RPC.&lt;br /&gt;
&lt;br /&gt;
LSRC2 offers a lot of functions. Please check the automatically generated [http://api.limesurvey.org/classes/remotecontrol_handle.html API Documentation].&lt;br /&gt;
LSRC2 offers the following functions:&lt;br /&gt;
&lt;br /&gt;
== Sessions ==&lt;br /&gt;
&lt;br /&gt;
=== get_session_key ===&lt;br /&gt;
&lt;br /&gt;
Using this function you can create a new XML/JSON-RPC session key. This is mandatory for all following LSRC2 function calls.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=php&amp;gt;&lt;br /&gt;
function get_session_key(string $username, string $password)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Return on success&#039;&#039;&#039;: (string) session key.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Return on error&#039;&#039;&#039;:  for protocol-level errors (invalid format etc), an error message. For invalid username and password, returns a null error and the result body contains a &#039;status&#039; name-value pair with the error message.&lt;br /&gt;
&lt;br /&gt;
=== release_session_key ===&lt;br /&gt;
&lt;br /&gt;
Using this function you can close a previously opened XML-RPC/JSON-RPC session.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=php&amp;gt;&lt;br /&gt;
function release_session_key(string $sSessionKey)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Parameter !! Description&lt;br /&gt;
|-&lt;br /&gt;
| sSessionKey || Auth credentials&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Return&#039;&#039;&#039;: Always &#039;OK&#039; (string)&lt;br /&gt;
&lt;br /&gt;
== Other functions ==&lt;br /&gt;
&lt;br /&gt;
{{Alert|For all other function , you have to refer to the [http://api.limesurvey.org/classes/remotecontrol_handle.html online API ] . If your LimeSurvey version is outdated, you can publish your API and look at it directly.}}&lt;br /&gt;
&lt;br /&gt;
= Example and helper =&lt;br /&gt;
&lt;br /&gt;
== PHP Example ==&lt;br /&gt;
&lt;br /&gt;
To include JSON-RPC in your application, you can write an application using the light-weight jsonRPCClient from the [https://github.com/weberhofer/jsonrpcphp jsonrpcphp Github repository]. The library can also get included [https://getcomposer.org/download/ by composer calling]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
composer require weberhofer/jsonrpcphp&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or by inclusion of the following lines in your composer.json file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=javascript&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;require&amp;quot;: {&lt;br /&gt;
        &amp;quot;weberhofer/jsonrpcphp&amp;quot;: &amp;quot;~2&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is a example how to connect to limesurvey:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
// without composer this line can be used&lt;br /&gt;
// require_once &#039;path/to/your/rpcclient/jsonRPCClient.php&#039;;&lt;br /&gt;
// with composer support just add the autoloader&lt;br /&gt;
include_once &#039;vendor/autoload.php&#039;;&lt;br /&gt;
&lt;br /&gt;
define( &#039;LS_BASEURL&#039;, &#039;https://localhost/limesurvey/&#039;);  // adjust this one to your actual LimeSurvey URL&lt;br /&gt;
define( &#039;LS_USER&#039;, &#039;rpcuser&#039; );&lt;br /&gt;
define( &#039;LS_PASSWORD&#039;, &#039;mypassword&#039; );&lt;br /&gt;
&lt;br /&gt;
// the survey to process&lt;br /&gt;
$survey_id=374699;&lt;br /&gt;
&lt;br /&gt;
// instantiate a new client&lt;br /&gt;
$myJSONRPCClient = new \org\jsonrpcphp\JsonRPCClient( LS_BASEURL.&#039;/admin/remotecontrol&#039; );&lt;br /&gt;
&lt;br /&gt;
// receive session key&lt;br /&gt;
$sessionKey= $myJSONRPCClient-&amp;gt;get_session_key( LS_USER, LS_PASSWORD );&lt;br /&gt;
&lt;br /&gt;
// receive all ids and info of groups belonging to a given survey&lt;br /&gt;
$groups = $myJSONRPCClient-&amp;gt;list_groups( $sessionKey, $survey_id );&lt;br /&gt;
print_r($groups, null );&lt;br /&gt;
&lt;br /&gt;
// release the session key&lt;br /&gt;
$myJSONRPCClient-&amp;gt;release_session_key( $sessionKey );&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== JAVA example ==&lt;br /&gt;
To decode and code your json calls you can use the library gson as you can see in the following example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
import java.io.IOException;&lt;br /&gt;
import java.io.UnsupportedEncodingException;&lt;br /&gt;
&lt;br /&gt;
import org.apache.http.HttpEntity;&lt;br /&gt;
import org.apache.http.HttpResponse;&lt;br /&gt;
import org.apache.http.client.methods.HttpPost;&lt;br /&gt;
import org.apache.http.entity.StringEntity;&lt;br /&gt;
import org.apache.http.impl.client.DefaultHttpClient;&lt;br /&gt;
import org.apache.http.util.EntityUtils;&lt;br /&gt;
&lt;br /&gt;
import com.google.gson.JsonElement;&lt;br /&gt;
import com.google.gson.JsonObject;&lt;br /&gt;
import com.google.gson.JsonParser;&lt;br /&gt;
&lt;br /&gt;
public class TestHttpClient {&lt;br /&gt;
	&lt;br /&gt;
    public static String parse(String jsonLine) {&lt;br /&gt;
	 JsonElement jelement = new JsonParser().parse(jsonLine);&lt;br /&gt;
	 JsonObject  jobject = jelement.getAsJsonObject();&lt;br /&gt;
	 String result = jobject.get(&amp;quot;result&amp;quot;).getAsString();&lt;br /&gt;
	 return result;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	&lt;br /&gt;
    public static void main(String[] args) throws UnsupportedEncodingException {&lt;br /&gt;
      DefaultHttpClient client = new DefaultHttpClient();          &lt;br /&gt;
         &lt;br /&gt;
      HttpPost post = new HttpPost(&amp;quot;https://PATH_OF_YOUR_SERVER/index.php/admin/remotecontrol&amp;quot;);&lt;br /&gt;
      post.setHeader(&amp;quot;Content-type&amp;quot;, &amp;quot;application/json&amp;quot;);&lt;br /&gt;
      post.setEntity( new StringEntity(&amp;quot;{\&amp;quot;method\&amp;quot;: \&amp;quot;get_session_key\&amp;quot;, \&amp;quot;params\&amp;quot;: [\&amp;quot;YOUR_USERNAME\&amp;quot;, \&amp;quot;YOUR_PASSWORD\&amp;quot; ], \&amp;quot;id\&amp;quot;: 1}&amp;quot;));&lt;br /&gt;
      try {&lt;br /&gt;
        HttpResponse response = client.execute(post);&lt;br /&gt;
        if(response.getStatusLine().getStatusCode() == 200){&lt;br /&gt;
            HttpEntity entity = response.getEntity();&lt;br /&gt;
            String sessionKey = parse(EntityUtils.toString(entity));&lt;br /&gt;
            post.setEntity( new StringEntity(&amp;quot;{\&amp;quot;method\&amp;quot;: \&amp;quot;list_groups\&amp;quot;, \&amp;quot;params\&amp;quot;: [ \&amp;quot;&amp;quot;+sessionKey+&amp;quot;\&amp;quot;, \&amp;quot;ID_SURVEY\&amp;quot; ], \&amp;quot;id\&amp;quot;: 1}&amp;quot;));&lt;br /&gt;
            response = client.execute(post);&lt;br /&gt;
            if(response.getStatusLine().getStatusCode() == 200){&lt;br /&gt;
                entity = response.getEntity();&lt;br /&gt;
                System.out.println(EntityUtils.toString(entity));&lt;br /&gt;
                }&lt;br /&gt;
           }&lt;br /&gt;
       &lt;br /&gt;
       &lt;br /&gt;
      } catch (IOException e) {&lt;br /&gt;
        e.printStackTrace();&lt;br /&gt;
      }&lt;br /&gt;
    }}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Python example and glue ==&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/TaiSHiNet/lime-py-api LimeSurvey API - Python 2 glue]&lt;br /&gt;
* [https://github.com/lindsay-stevens/limesurveyrc2api LimeSurvey API - Basic client library in Python 3]. Includes tests. Listed on Pypi: pip install limesurveyrc2api&lt;br /&gt;
&lt;br /&gt;
The following code runs with Python 2 and requires some adaptation to work with Python 3.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
import urllib&lt;br /&gt;
import urllib2&lt;br /&gt;
import json&lt;br /&gt;
import sys&lt;br /&gt;
# There is an generic json-rpc implemantation in Python but it dose not work for me in this case so I worte Some functions &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
        &lt;br /&gt;
def get_session_key():&lt;br /&gt;
    req = urllib2.Request(url=&#039;https://myurl/index.php/admin/remotecontrol&#039;,\&lt;br /&gt;
                          data=&#039;{\&amp;quot;method\&amp;quot;:\&amp;quot;get_session_key\&amp;quot;,\&amp;quot;params\&amp;quot;:[\&amp;quot;admin\&amp;quot;,\&amp;quot;mypassword\&amp;quot;],\&amp;quot;id\&amp;quot;:1}&#039;)&lt;br /&gt;
    req.add_header(&#039;content-type&#039;, &#039;application/json&#039;)&lt;br /&gt;
    req.add_header(&#039;connection&#039;, &#039;Keep-Alive&#039;)&lt;br /&gt;
    try:&lt;br /&gt;
        f = urllib2.urlopen(req)&lt;br /&gt;
        myretun = f.read()&lt;br /&gt;
        #print myretun&lt;br /&gt;
        j=json.loads(myretun)&lt;br /&gt;
        return j[&#039;result&#039;]&lt;br /&gt;
    except :&lt;br /&gt;
        e = sys.exc_info()[0]&lt;br /&gt;
        print ( &amp;quot;&amp;lt;p&amp;gt;Error: %s&amp;lt;/p&amp;gt;&amp;quot; % e )&lt;br /&gt;
		&lt;br /&gt;
def get_question_properties(skey,QuestionID):&lt;br /&gt;
    req = urllib2.Request(url=&#039;https://myurl/index.php/admin/remotecontrol&#039;,\&lt;br /&gt;
                          data=&#039;{\&amp;quot;method\&amp;quot;:\&amp;quot;get_question_properties\&amp;quot;,\&amp;quot;params\&amp;quot;:[\&amp;quot;&#039;+skey+&#039;\&amp;quot;,&#039;+QuestionID&lt;br /&gt;
                                    +&#039;,[\&amp;quot;gid\&amp;quot;,\&amp;quot;type\&amp;quot;,\&amp;quot;help\&amp;quot;,\&amp;quot;language\&amp;quot;,\&amp;quot;sid\&amp;quot;,\&amp;quot;question_order\&amp;quot;,\&amp;quot;question\&amp;quot;,\&amp;quot;subquestions\&amp;quot;]],\&amp;quot;id\&amp;quot;: 1}&#039;)&lt;br /&gt;
&lt;br /&gt;
    req.add_header(&#039;content-type&#039;, &#039;application/json&#039;)&lt;br /&gt;
    req.add_header(&#039;connection&#039;, &#039;Keep-Alive&#039;)&lt;br /&gt;
    try:&lt;br /&gt;
        f = urllib2.urlopen(req)&lt;br /&gt;
        myretun = f.read()&lt;br /&gt;
        #print myretun&lt;br /&gt;
        j=json.loads(myretun)&lt;br /&gt;
        return j[&#039;result&#039;]&lt;br /&gt;
    except :&lt;br /&gt;
        e = sys.exc_info()[0]&lt;br /&gt;
        print ( &amp;quot;&amp;lt;p&amp;gt;Error: %s&amp;lt;/p&amp;gt;&amp;quot; % e )&lt;br /&gt;
&lt;br /&gt;
		&lt;br /&gt;
def release_session_key(relkey):&lt;br /&gt;
    req = urllib2.Request(url=&#039;https://myurl/index.php/admin/remotecontrol&#039;,\&lt;br /&gt;
                          data=&#039;{\&amp;quot;method\&amp;quot;:\&amp;quot;release_session_key\&amp;quot;,\&amp;quot;params\&amp;quot;:[\&amp;quot;&#039;+relkey+&#039;\&amp;quot;],\&amp;quot;id\&amp;quot;:1}&#039;)&lt;br /&gt;
    req.add_header(&#039;content-type&#039;, &#039;application/json&#039;)&lt;br /&gt;
    req.add_header(&#039;connection&#039;, &#039;Keep-Alive&#039;)&lt;br /&gt;
    try:&lt;br /&gt;
        f = urllib2.urlopen(req)&lt;br /&gt;
        myretun = f.read()&lt;br /&gt;
        #print myretun&lt;br /&gt;
        j=json.loads(myretun)&lt;br /&gt;
        return j[&#039;result&#039;]&lt;br /&gt;
    except :&lt;br /&gt;
        e = sys.exc_info()[0]&lt;br /&gt;
        print ( &amp;quot;&amp;lt;p&amp;gt;Error: %s&amp;lt;/p&amp;gt;&amp;quot; % e )&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def export_responses2(skey,sid):&lt;br /&gt;
    req = urllib2.Request(url=&#039;https://myurl/index.php/admin/remotecontrol&#039;,\&lt;br /&gt;
                          data=&#039;{\&amp;quot;method\&amp;quot;:\&amp;quot;export_responses\&amp;quot;,\&amp;quot;params\&amp;quot;:[\&amp;quot;&#039;+skey+&#039;\&amp;quot;,\&amp;quot;&#039;+sid+&#039;\&amp;quot;,\&amp;quot;csv\&amp;quot;,\&amp;quot;de\&amp;quot;,\&amp;quot;full\&amp;quot;],\&lt;br /&gt;
&amp;quot;id\&amp;quot;: 1}&#039;)&lt;br /&gt;
    req.add_header(&#039;content-type&#039;, &#039;application/json&#039;)&lt;br /&gt;
    req.add_header(&#039;connection&#039;, &#039;Keep-Alive&#039;)&lt;br /&gt;
    try:&lt;br /&gt;
        f = urllib2.urlopen(req)&lt;br /&gt;
        myretun = f.read()&lt;br /&gt;
        #print myretun&lt;br /&gt;
        j=json.loads(myretun)&lt;br /&gt;
        return j[&#039;result&#039;]&lt;br /&gt;
    except :&lt;br /&gt;
        e = sys.exc_info()[0]&lt;br /&gt;
        print ( &amp;quot;&amp;lt;p&amp;gt;Error: %s&amp;lt;/p&amp;gt;&amp;quot; % e )		&lt;br /&gt;
&lt;br /&gt;
		&lt;br /&gt;
mykey=get_session_key()&lt;br /&gt;
print export_responses2(mykey,&#039;566237&#039;).decode(&#039;base64&#039;)&lt;br /&gt;
get_question_properties(mykey,&#039;574&#039;)&lt;br /&gt;
print release_session_key(mykey)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== NodeJS example ==&lt;br /&gt;
&lt;br /&gt;
This script require request, you can include easily with the command &lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
npm install request&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is a example how to connect to limesurvey:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
var request = require(&#039;request&#039;);&lt;br /&gt;
&lt;br /&gt;
//******GLOBAL***************&lt;br /&gt;
var SESSIONKEY=&amp;quot;&amp;quot;;&lt;br /&gt;
var options = {&lt;br /&gt;
  url: &amp;quot;https://xxxxxxxxxxxxxxxx/index.php/admin/remotecontrol&amp;quot;,&lt;br /&gt;
  method: &amp;quot;POST&amp;quot;,&lt;br /&gt;
  headers: {&lt;br /&gt;
    &#039;user-agent&#039;: &#039;Apache-HttpClient/4.2.2 (java 1.5)&#039;,&lt;br /&gt;
    &#039;host&#039;: &#039;xxxxxxxxxxxxxxxx&#039;,&lt;br /&gt;
    &#039;path&#039;: &#039;/index.php/admin/remotecontrol&#039;,&lt;br /&gt;
    &#039;connection&#039;: &#039;keep-alive&#039;,&lt;br /&gt;
    &#039;content-type&#039;: &#039;application/json&#039;&lt;br /&gt;
  }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
//*******AUTHENTIFICATION*******&lt;br /&gt;
options.body = JSON.stringify({method:&#039;get_session_key&#039;,params:[&#039;myusername&#039;,&#039;mypassword&#039;],id:1});&lt;br /&gt;
&lt;br /&gt;
request(options, function(error, response, body){&lt;br /&gt;
  if (!error &amp;amp;&amp;amp; response.statusCode == 200) {&lt;br /&gt;
      body = JSON.parse(body);&lt;br /&gt;
&lt;br /&gt;
    //*********KEEP THE KEY*********  &lt;br /&gt;
    if(SESSIONKEY===&amp;quot;&amp;quot;) {&lt;br /&gt;
      console.log(&amp;quot;NEW KEY --&amp;gt;&amp;quot;+body.result);&lt;br /&gt;
      SESSIONKEY=body.result;&lt;br /&gt;
      nextFonction();&lt;br /&gt;
    } &lt;br /&gt;
  }&lt;br /&gt;
  else console.log(&amp;quot;ERROR --&amp;gt;&amp;quot;+body);  &lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== R example and helper ==&lt;br /&gt;
&lt;br /&gt;
The easiest way to use lsrc2 is by means of the limer package, See https://github.com/cloudyr/limer&lt;br /&gt;
&lt;br /&gt;
Example of usage of this client&lt;br /&gt;
&amp;lt;source lang=R&amp;gt;&lt;br /&gt;
# first limer (check version: must be recent) must be installed&lt;br /&gt;
if(!require(&amp;quot;devtools&amp;quot;)) {&lt;br /&gt;
  install.packages(&amp;quot;devtools&amp;quot;)&lt;br /&gt;
  library(&amp;quot;devtools&amp;quot;)&lt;br /&gt;
}&lt;br /&gt;
install_github(&amp;quot;cloudyr/limer&amp;quot;)&lt;br /&gt;
#############################################################&lt;br /&gt;
&lt;br /&gt;
library(limer)&lt;br /&gt;
&lt;br /&gt;
#change the next options (website, user, password)&lt;br /&gt;
options&lt;br /&gt;
(lime_api = &#039;https://www.XXX.nl/index.php/admin/remotecontrol&#039;)&lt;br /&gt;
options(lime_username = &#039;user&#039;)&lt;br /&gt;
options(lime_password = &#039;password&#039;)&lt;br /&gt;
#############################################################&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# first get a session access key&lt;br /&gt;
get_session_key()&lt;br /&gt;
&lt;br /&gt;
# list all surveys. A dataframe is returned&lt;br /&gt;
survey_df&amp;lt;-call_limer(method=&#039;list_surveys&#039;)&lt;br /&gt;
print(survey_df)&lt;br /&gt;
#    sid           surveyls_title startdate             expires active&lt;br /&gt;
#1  999999  XXXX               NA 2016-03-08 15:20:30      Y&lt;br /&gt;
#2  999998  XXXX               NA   &amp;lt;NA&amp;gt;      Y&lt;br /&gt;
&lt;br /&gt;
#Read the data of the first survey (sid=999999) into a data.frame. &lt;br /&gt;
#Notice that the default sLanguageCode = en, so maybe you have to &lt;br /&gt;
#specify another language (here: All languages)&lt;br /&gt;
data&amp;lt;- get_responses(iSurveyID= 999999, sLanguageCode= &#039;&#039;, sResponseType=&#039;short&#039;)&lt;br /&gt;
        &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= JSON-RPC notes =&lt;br /&gt;
&lt;br /&gt;
The content-type of the HTTP request must be application/json.  Most formatting errors are a failure to set the content-type header will result in a null response from the server (not a JSON response).  Below is an example of a valid request and response pair.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;Request:&lt;br /&gt;
&lt;br /&gt;
 HTTP headers:&lt;br /&gt;
&lt;br /&gt;
   content-type=application/json&lt;br /&gt;
&lt;br /&gt;
   connection=Keep-Alive&lt;br /&gt;
&lt;br /&gt;
   host=mylimesurveyhost.com&lt;br /&gt;
&lt;br /&gt;
   content-length=67&lt;br /&gt;
&lt;br /&gt;
   user-agent=Apache-HttpClient/4.2.2 (java 1.5)&lt;br /&gt;
&lt;br /&gt;
 Post body:&lt;br /&gt;
&lt;br /&gt;
   {&amp;quot;method&amp;quot;:&amp;quot;get_session_key&amp;quot;,&amp;quot;params&amp;quot;:[&amp;quot;admin&amp;quot;,&amp;quot;mypassword&amp;quot;],&amp;quot;id&amp;quot;:1}&lt;br /&gt;
&lt;br /&gt;
Response body:&lt;br /&gt;
&lt;br /&gt;
 {&amp;quot;id&amp;quot;:1,&amp;quot;result&amp;quot;:&amp;quot;6htqat38fyr4v7iu72nqgv7xgavkvfcz&amp;quot;,&amp;quot;error&amp;quot;:null}&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>LimeAJ</name></author>
	</entry>
	<entry>
		<id>https://www.limesurvey.org/manual/index.php?title=RemoteControl_2_API&amp;diff=76440</id>
		<title>RemoteControl 2 API</title>
		<link rel="alternate" type="text/html" href="https://www.limesurvey.org/manual/index.php?title=RemoteControl_2_API&amp;diff=76440"/>
		<updated>2017-08-28T13:43:22Z</updated>

		<summary type="html">&lt;p&gt;LimeAJ: /* PHP Example */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
=Introduction=&lt;br /&gt;
&lt;br /&gt;
LimeSurvey RemoteControl 2 is a XML-RPC/JSON-RPC based web service available in LimeSurvey 2.0 or more recent which offers &#039;&#039;&#039;various [https://api.limesurvey.org/classes/remotecontrol_handle.html API functions]&#039;&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
LSRC2 makes it possible for developers to control specific functionality of LimeSurvey from any other application, without being restricted to PHP as a programming language.&lt;br /&gt;
&lt;br /&gt;
The following features are planned:&lt;br /&gt;
* start a predefined survey (change titles and things)&lt;br /&gt;
* add predefined groups or questions&lt;br /&gt;
* activate the survey, restrict it to start and endtime&lt;br /&gt;
* make it closed,&lt;br /&gt;
* add participant data/tokens when you need them&lt;br /&gt;
* return the unused tokens to the main application&lt;br /&gt;
* get a fieldmap for a survey,&lt;br /&gt;
* invite or remind the participants of your survey&lt;br /&gt;
&lt;br /&gt;
...and much more&lt;br /&gt;
&lt;br /&gt;
==Requirements==&lt;br /&gt;
* libXML installed&lt;br /&gt;
&lt;br /&gt;
=Setup=&lt;br /&gt;
&lt;br /&gt;
== How to configure LSRC2==&lt;br /&gt;
&lt;br /&gt;
In a default LimeSurvey installation LSRC2 is disabled. In order to use LSRC2 you must first enable the service, and then adjust the settings to suit your needs. To enable LSRC2 login to the LimeSurvey administration, go to [[Global settings]], choose the tab &#039;Interfaces&#039; and select one of the two RPC services (XML-RPC or JSON-RPC) service.&lt;br /&gt;
&lt;br /&gt;
== Security==&lt;br /&gt;
&lt;br /&gt;
LSRC2 uses the same security measures as the normal administration login. That means that the permission set of the used username and password is the same as if you would login in the administration with that user/password. Also LSRC2 is protected against brute-force password cracking - like the normal administration login.&lt;br /&gt;
&lt;br /&gt;
=How to use LSRC2=&lt;br /&gt;
&lt;br /&gt;
The basic LSRC2 URL is: http://&amp;lt;your_domain&amp;gt;/&amp;lt;your_limesurvey_dir&amp;gt;/index.php/admin/remotecontrol&lt;br /&gt;
&lt;br /&gt;
LSRC2 fully complies to the [http://www.xmlrpc.com/ XML-RPC specification] and JSON-RPC version 1 specifications. We recommend in general to use JSON-RPC because it is well tested and has a much smaller footprint than XML-RPC.&lt;br /&gt;
&lt;br /&gt;
LSRC2 offers a lot of functions. Please check the automatically generated [http://api.limesurvey.org/classes/remotecontrol_handle.html API Documentation].&lt;br /&gt;
LSRC2 offers the following functions:&lt;br /&gt;
&lt;br /&gt;
== Sessions ==&lt;br /&gt;
&lt;br /&gt;
=== get_session_key ===&lt;br /&gt;
&lt;br /&gt;
Using this function you can create a new XML/JSON-RPC session key. This is mandatory for all following LSRC2 function calls.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=php&amp;gt;&lt;br /&gt;
function get_session_key(string $username, string $password)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Return on success&#039;&#039;&#039;: (string) session key.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Return on error&#039;&#039;&#039;:  for protocol-level errors (invalid format etc), an error message. For invalid username and password, returns a null error and the result body contains a &#039;status&#039; name-value pair with the error message.&lt;br /&gt;
&lt;br /&gt;
=== release_session_key ===&lt;br /&gt;
&lt;br /&gt;
Using this function you can close a previously opened XML-RPC/JSON-RPC session.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=php&amp;gt;&lt;br /&gt;
function release_session_key(string $sSessionKey)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Parameter !! Description&lt;br /&gt;
|-&lt;br /&gt;
| sSessionKey || Auth credentials&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Return&#039;&#039;&#039;: Always &#039;OK&#039; (string)&lt;br /&gt;
&lt;br /&gt;
== Other functions ==&lt;br /&gt;
&lt;br /&gt;
{{Alert|For all other function , you have to refer to the [http://api.limesurvey.org/classes/remotecontrol_handle.html online API ] . If your LimeSurvey version is outdated, you can publish your API and look at it directly.}}&lt;br /&gt;
&lt;br /&gt;
= Example and helper =&lt;br /&gt;
&lt;br /&gt;
== PHP Example ==&lt;br /&gt;
&lt;br /&gt;
To include JSON-RPC in your application, you can write an application using the light-weight jsonRPCClient from the [https://github.com/weberhofer/jsonrpcphp jsonrpcphp Github repository]. The library can also get included [https://getcomposer.org/download/ by composer calling]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
composer require weberhofer/jsonrpcphp&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or by inclusion of the following lines in your composer.json file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=javascript&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;require&amp;quot;: {&lt;br /&gt;
        &amp;quot;weberhofer/jsonrpcphp&amp;quot;: &amp;quot;~2&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is a example how to connect to limesurvey:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
// without composer this line can be used&lt;br /&gt;
// require_once &#039;path/to/your/rpcclient/jsonRPCClient.php&#039;;&lt;br /&gt;
// with composer support just add the autoloader&lt;br /&gt;
include_once &#039;vendor/autoload.php&#039;;&lt;br /&gt;
&lt;br /&gt;
define( &#039;LS_BASEURL&#039;, &#039;https://localhost/limesurvey/&#039;);  // adjust this one to your actual LimeSurvey URL&lt;br /&gt;
define( &#039;LS_USER&#039;, &#039;rpcuser&#039; );&lt;br /&gt;
define( &#039;LS_PASSWORD&#039;, &#039;mypassword&#039; );&lt;br /&gt;
&lt;br /&gt;
// the survey to process&lt;br /&gt;
$survey_id=374699;&lt;br /&gt;
&lt;br /&gt;
// instantiate a new client&lt;br /&gt;
$myJSONRPCClient = new \org\jsonrpcphp\JsonRPCClient( LS_BASEURL.&#039;/admin/remotecontrol&#039; );&lt;br /&gt;
&lt;br /&gt;
// receive session key&lt;br /&gt;
$sessionKey= $myJSONRPCClient-&amp;gt;get_session_key( LS_USER, LS_PASSWORD );&lt;br /&gt;
&lt;br /&gt;
// receive all ids and info of groups belonging to a given survey&lt;br /&gt;
$groups = $myJSONRPCClient-&amp;gt;list_groups( $sessionKey, $survey_id );&lt;br /&gt;
print_r($groups, null );&lt;br /&gt;
&lt;br /&gt;
// release the session key&lt;br /&gt;
$myJSONRPCClient-&amp;gt;release_session_key( $sessionKey );&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== JAVA example ==&lt;br /&gt;
To decode and code your json calls you can use the library gson as you can see in the following example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
import java.io.IOException;&lt;br /&gt;
import java.io.UnsupportedEncodingException;&lt;br /&gt;
&lt;br /&gt;
import org.apache.http.HttpEntity;&lt;br /&gt;
import org.apache.http.HttpResponse;&lt;br /&gt;
import org.apache.http.client.methods.HttpPost;&lt;br /&gt;
import org.apache.http.entity.StringEntity;&lt;br /&gt;
import org.apache.http.impl.client.DefaultHttpClient;&lt;br /&gt;
import org.apache.http.util.EntityUtils;&lt;br /&gt;
&lt;br /&gt;
import com.google.gson.JsonElement;&lt;br /&gt;
import com.google.gson.JsonObject;&lt;br /&gt;
import com.google.gson.JsonParser;&lt;br /&gt;
&lt;br /&gt;
public class TestHttpClient {&lt;br /&gt;
	&lt;br /&gt;
    public static String parse(String jsonLine) {&lt;br /&gt;
	 JsonElement jelement = new JsonParser().parse(jsonLine);&lt;br /&gt;
	 JsonObject  jobject = jelement.getAsJsonObject();&lt;br /&gt;
	 String result = jobject.get(&amp;quot;result&amp;quot;).getAsString();&lt;br /&gt;
	 return result;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	&lt;br /&gt;
    public static void main(String[] args) throws UnsupportedEncodingException {&lt;br /&gt;
      DefaultHttpClient client = new DefaultHttpClient();          &lt;br /&gt;
         &lt;br /&gt;
      HttpPost post = new HttpPost(&amp;quot;https://PATH_OF_YOUR_SERVER/index.php/admin/remotecontrol&amp;quot;);&lt;br /&gt;
      post.setHeader(&amp;quot;Content-type&amp;quot;, &amp;quot;application/json&amp;quot;);&lt;br /&gt;
      post.setEntity( new StringEntity(&amp;quot;{\&amp;quot;method\&amp;quot;: \&amp;quot;get_session_key\&amp;quot;, \&amp;quot;params\&amp;quot;: [\&amp;quot;YOUR_USERNAME\&amp;quot;, \&amp;quot;YOUR_PASSWORD\&amp;quot; ], \&amp;quot;id\&amp;quot;: 1}&amp;quot;));&lt;br /&gt;
      try {&lt;br /&gt;
        HttpResponse response = client.execute(post);&lt;br /&gt;
        if(response.getStatusLine().getStatusCode() == 200){&lt;br /&gt;
            HttpEntity entity = response.getEntity();&lt;br /&gt;
            String sessionKey = parse(EntityUtils.toString(entity));&lt;br /&gt;
            post.setEntity( new StringEntity(&amp;quot;{\&amp;quot;method\&amp;quot;: \&amp;quot;list_groups\&amp;quot;, \&amp;quot;params\&amp;quot;: [ \&amp;quot;&amp;quot;+sessionKey+&amp;quot;\&amp;quot;, \&amp;quot;ID_SURVEY\&amp;quot; ], \&amp;quot;id\&amp;quot;: 1}&amp;quot;));&lt;br /&gt;
            response = client.execute(post);&lt;br /&gt;
            if(response.getStatusLine().getStatusCode() == 200){&lt;br /&gt;
                entity = response.getEntity();&lt;br /&gt;
                System.out.println(EntityUtils.toString(entity));&lt;br /&gt;
                }&lt;br /&gt;
           }&lt;br /&gt;
       &lt;br /&gt;
       &lt;br /&gt;
      } catch (IOException e) {&lt;br /&gt;
        e.printStackTrace();&lt;br /&gt;
      }&lt;br /&gt;
    }}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Python example and glue ==&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/TaiSHiNet/lime-py-api LimeSurvey API - Python 2 glue]&lt;br /&gt;
* [https://github.com/lindsay-stevens/limesurveyrc2api LimeSurvey API - Basic client library in Python 3]. Includes tests. Listed on Pypi: pip install limesurveyrc2api&lt;br /&gt;
&lt;br /&gt;
The following code runs with Python 2 and requires some adaptation to work with Python 3.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
import urllib&lt;br /&gt;
import urllib2&lt;br /&gt;
import json&lt;br /&gt;
import sys&lt;br /&gt;
# There is an generic json-rpc implemantation in Python but it dose not work for me in this case so I worte Some functions &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
        &lt;br /&gt;
def get_session_key():&lt;br /&gt;
    req = urllib2.Request(url=&#039;https://myurl/index.php/admin/remotecontrol&#039;,\&lt;br /&gt;
                          data=&#039;{\&amp;quot;method\&amp;quot;:\&amp;quot;get_session_key\&amp;quot;,\&amp;quot;params\&amp;quot;:[\&amp;quot;admin\&amp;quot;,\&amp;quot;mypassword\&amp;quot;],\&amp;quot;id\&amp;quot;:1}&#039;)&lt;br /&gt;
    req.add_header(&#039;content-type&#039;, &#039;application/json&#039;)&lt;br /&gt;
    req.add_header(&#039;connection&#039;, &#039;Keep-Alive&#039;)&lt;br /&gt;
    try:&lt;br /&gt;
        f = urllib2.urlopen(req)&lt;br /&gt;
        myretun = f.read()&lt;br /&gt;
        #print myretun&lt;br /&gt;
        j=json.loads(myretun)&lt;br /&gt;
        return j[&#039;result&#039;]&lt;br /&gt;
    except :&lt;br /&gt;
        e = sys.exc_info()[0]&lt;br /&gt;
        print ( &amp;quot;&amp;lt;p&amp;gt;Error: %s&amp;lt;/p&amp;gt;&amp;quot; % e )&lt;br /&gt;
		&lt;br /&gt;
def get_question_properties(skey,QuestionID):&lt;br /&gt;
    req = urllib2.Request(url=&#039;https://myurl/index.php/admin/remotecontrol&#039;,\&lt;br /&gt;
                          data=&#039;{\&amp;quot;method\&amp;quot;:\&amp;quot;get_question_properties\&amp;quot;,\&amp;quot;params\&amp;quot;:[\&amp;quot;&#039;+skey+&#039;\&amp;quot;,&#039;+QuestionID&lt;br /&gt;
                                    +&#039;,[\&amp;quot;gid\&amp;quot;,\&amp;quot;type\&amp;quot;,\&amp;quot;help\&amp;quot;,\&amp;quot;language\&amp;quot;,\&amp;quot;sid\&amp;quot;,\&amp;quot;question_order\&amp;quot;,\&amp;quot;question\&amp;quot;,\&amp;quot;subquestions\&amp;quot;]],\&amp;quot;id\&amp;quot;: 1}&#039;)&lt;br /&gt;
&lt;br /&gt;
    req.add_header(&#039;content-type&#039;, &#039;application/json&#039;)&lt;br /&gt;
    req.add_header(&#039;connection&#039;, &#039;Keep-Alive&#039;)&lt;br /&gt;
    try:&lt;br /&gt;
        f = urllib2.urlopen(req)&lt;br /&gt;
        myretun = f.read()&lt;br /&gt;
        #print myretun&lt;br /&gt;
        j=json.loads(myretun)&lt;br /&gt;
        return j[&#039;result&#039;]&lt;br /&gt;
    except :&lt;br /&gt;
        e = sys.exc_info()[0]&lt;br /&gt;
        print ( &amp;quot;&amp;lt;p&amp;gt;Error: %s&amp;lt;/p&amp;gt;&amp;quot; % e )&lt;br /&gt;
&lt;br /&gt;
		&lt;br /&gt;
def release_session_key(relkey):&lt;br /&gt;
    req = urllib2.Request(url=&#039;https://myurl/index.php/admin/remotecontrol&#039;,\&lt;br /&gt;
                          data=&#039;{\&amp;quot;method\&amp;quot;:\&amp;quot;release_session_key\&amp;quot;,\&amp;quot;params\&amp;quot;:[\&amp;quot;&#039;+relkey+&#039;\&amp;quot;],\&amp;quot;id\&amp;quot;:1}&#039;)&lt;br /&gt;
    req.add_header(&#039;content-type&#039;, &#039;application/json&#039;)&lt;br /&gt;
    req.add_header(&#039;connection&#039;, &#039;Keep-Alive&#039;)&lt;br /&gt;
    try:&lt;br /&gt;
        f = urllib2.urlopen(req)&lt;br /&gt;
        myretun = f.read()&lt;br /&gt;
        #print myretun&lt;br /&gt;
        j=json.loads(myretun)&lt;br /&gt;
        return j[&#039;result&#039;]&lt;br /&gt;
    except :&lt;br /&gt;
        e = sys.exc_info()[0]&lt;br /&gt;
        print ( &amp;quot;&amp;lt;p&amp;gt;Error: %s&amp;lt;/p&amp;gt;&amp;quot; % e )&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def export_responses2(skey,sid):&lt;br /&gt;
    req = urllib2.Request(url=&#039;https://myurl/index.php/admin/remotecontrol&#039;,\&lt;br /&gt;
                          data=&#039;{\&amp;quot;method\&amp;quot;:\&amp;quot;export_responses\&amp;quot;,\&amp;quot;params\&amp;quot;:[\&amp;quot;&#039;+skey+&#039;\&amp;quot;,\&amp;quot;&#039;+sid+&#039;\&amp;quot;,\&amp;quot;csv\&amp;quot;,\&amp;quot;de\&amp;quot;,\&amp;quot;full\&amp;quot;],\&lt;br /&gt;
&amp;quot;id\&amp;quot;: 1}&#039;)&lt;br /&gt;
    req.add_header(&#039;content-type&#039;, &#039;application/json&#039;)&lt;br /&gt;
    req.add_header(&#039;connection&#039;, &#039;Keep-Alive&#039;)&lt;br /&gt;
    try:&lt;br /&gt;
        f = urllib2.urlopen(req)&lt;br /&gt;
        myretun = f.read()&lt;br /&gt;
        #print myretun&lt;br /&gt;
        j=json.loads(myretun)&lt;br /&gt;
        return j[&#039;result&#039;]&lt;br /&gt;
    except :&lt;br /&gt;
        e = sys.exc_info()[0]&lt;br /&gt;
        print ( &amp;quot;&amp;lt;p&amp;gt;Error: %s&amp;lt;/p&amp;gt;&amp;quot; % e )		&lt;br /&gt;
&lt;br /&gt;
		&lt;br /&gt;
mykey=get_session_key()&lt;br /&gt;
print export_responses2(mykey,&#039;566237&#039;).decode(&#039;base64&#039;)&lt;br /&gt;
get_question_properties(mykey,&#039;574&#039;)&lt;br /&gt;
print release_session_key(mykey)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== NodeJS example ==&lt;br /&gt;
&lt;br /&gt;
This script require request, you can include easily with the command &lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
npm install request&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is a example how to connect to limesurvey:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
var request = require(&#039;request&#039;);&lt;br /&gt;
&lt;br /&gt;
//******GLOBAL***************&lt;br /&gt;
var SESSIONKEY=&amp;quot;&amp;quot;;&lt;br /&gt;
var options = {&lt;br /&gt;
  url: &amp;quot;https://xxxxxxxxxxxxxxxx/index.php/admin/remotecontrol&amp;quot;,&lt;br /&gt;
  method: &amp;quot;POST&amp;quot;,&lt;br /&gt;
  headers: {&lt;br /&gt;
    &#039;user-agent&#039;: &#039;Apache-HttpClient/4.2.2 (java 1.5)&#039;,&lt;br /&gt;
    &#039;host&#039;: &#039;xxxxxxxxxxxxxxxx&#039;,&lt;br /&gt;
    &#039;path&#039;: &#039;/index.php/admin/remotecontrol&#039;,&lt;br /&gt;
    &#039;connection&#039;: &#039;keep-alive&#039;,&lt;br /&gt;
    &#039;content-type&#039;: &#039;application/json&#039;&lt;br /&gt;
  }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
//*******AUTHENTIFICATION*******&lt;br /&gt;
options.body = JSON.stringify({method:&#039;get_session_key&#039;,params:[&#039;myusername&#039;,&#039;mypassword&#039;],id:1});&lt;br /&gt;
&lt;br /&gt;
request(options, function(error, response, body){&lt;br /&gt;
  if (!error &amp;amp;&amp;amp; response.statusCode == 200) {&lt;br /&gt;
      body = JSON.parse(body);&lt;br /&gt;
&lt;br /&gt;
    //*********KEEP THE KEY*********  &lt;br /&gt;
    if(SESSIONKEY===&amp;quot;&amp;quot;) {&lt;br /&gt;
      console.log(&amp;quot;NEW KEY --&amp;gt;&amp;quot;+body.result);&lt;br /&gt;
      SESSIONKEY=body.result;&lt;br /&gt;
      nextFonction();&lt;br /&gt;
    } &lt;br /&gt;
  }&lt;br /&gt;
  else console.log(&amp;quot;ERROR --&amp;gt;&amp;quot;+body);  &lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== R example and helper ==&lt;br /&gt;
&lt;br /&gt;
The easiest way to use lsrc2 is by means of the limer package, See https://github.com/cloudyr/limer&lt;br /&gt;
&lt;br /&gt;
Example of usage of this client&lt;br /&gt;
&amp;lt;source lang=R&amp;gt;&lt;br /&gt;
# first limer (check version: must be recent) must be installed&lt;br /&gt;
if(!require(&amp;quot;devtools&amp;quot;)) {&lt;br /&gt;
  install.packages(&amp;quot;devtools&amp;quot;)&lt;br /&gt;
  library(&amp;quot;devtools&amp;quot;)&lt;br /&gt;
}&lt;br /&gt;
install_github(&amp;quot;cloudyr/limer&amp;quot;)&lt;br /&gt;
#############################################################&lt;br /&gt;
&lt;br /&gt;
library(limer)&lt;br /&gt;
&lt;br /&gt;
#change the next options (website, user, password)&lt;br /&gt;
options&lt;br /&gt;
(lime_api = &#039;https://www.XXX.nl/index.php/admin/remotecontrol&#039;)&lt;br /&gt;
options(lime_username = &#039;user&#039;)&lt;br /&gt;
options(lime_password = &#039;password&#039;)&lt;br /&gt;
#############################################################&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# first get a session access key&lt;br /&gt;
get_session_key()&lt;br /&gt;
&lt;br /&gt;
# list all surveys. A dataframe is returned&lt;br /&gt;
survey_df&amp;lt;-call_limer(method=&#039;list_surveys&#039;)&lt;br /&gt;
print(survey_df)&lt;br /&gt;
#    sid           surveyls_title startdate             expires active&lt;br /&gt;
#1  999999  XXXX               NA 2016-03-08 15:20:30      Y&lt;br /&gt;
#2  999998  XXXX               NA   &amp;lt;NA&amp;gt;      Y&lt;br /&gt;
&lt;br /&gt;
#Read the data of the first survey (sid=999999) into a data.frame. &lt;br /&gt;
#Notice that the default sLanguageCode = en, so maybe you have to &lt;br /&gt;
#specify another language (here: All languages)&lt;br /&gt;
data&amp;lt;- get_responses(iSurveyID= 999999, sLanguageCode= &#039;&#039;, sResponseType=&#039;short&#039;)&lt;br /&gt;
        &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= JSON-RPC notes =&lt;br /&gt;
&lt;br /&gt;
The content-type of the HTTP request must be application/json.  Most formatting errors or a failure to set the content-type header will result in a null response from the server (not a JSON response).  Below is an example of a valid request and response pair.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;Request:&lt;br /&gt;
&lt;br /&gt;
 HTTP headers:&lt;br /&gt;
&lt;br /&gt;
   content-type=application/json&lt;br /&gt;
&lt;br /&gt;
   connection=Keep-Alive&lt;br /&gt;
&lt;br /&gt;
   host=mylimesurveyhost.com&lt;br /&gt;
&lt;br /&gt;
   content-length=67&lt;br /&gt;
&lt;br /&gt;
   user-agent=Apache-HttpClient/4.2.2 (java 1.5)&lt;br /&gt;
&lt;br /&gt;
 Post body:&lt;br /&gt;
&lt;br /&gt;
   {&amp;quot;method&amp;quot;:&amp;quot;get_session_key&amp;quot;,&amp;quot;params&amp;quot;:[&amp;quot;admin&amp;quot;,&amp;quot;mypassword&amp;quot;],&amp;quot;id&amp;quot;:1}&lt;br /&gt;
&lt;br /&gt;
Response body:&lt;br /&gt;
&lt;br /&gt;
 {&amp;quot;id&amp;quot;:1,&amp;quot;result&amp;quot;:&amp;quot;6htqat38fyr4v7iu72nqgv7xgavkvfcz&amp;quot;,&amp;quot;error&amp;quot;:null}&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>LimeAJ</name></author>
	</entry>
	<entry>
		<id>https://www.limesurvey.org/manual/index.php?title=Optional_settings&amp;diff=76439</id>
		<title>Optional settings</title>
		<link rel="alternate" type="text/html" href="https://www.limesurvey.org/manual/index.php?title=Optional_settings&amp;diff=76439"/>
		<updated>2017-08-25T20:01:18Z</updated>

		<summary type="html">&lt;p&gt;LimeAJ: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;languages /&amp;gt; &amp;lt;translate&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:63--&amp;gt;&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
The following section is addressed to those of you who would like to edit those configuration settings that could not be modified with the help of the GUI (Graphical User Interface) of the LimeSurvey installation. Please bear in mind that all the changes from the LimeSurvey root directory are done at your own risk. Nevertheless, in the case in which you are experiencing problems/need further guidance, join the [https://www.limesurvey.org/forum discussion forums] or the [irc://irc.freenode.net/limesurvey|IRC IRC channel] for help from the LimeSurvey community.&lt;br /&gt;
&lt;br /&gt;
=Introduction= &amp;lt;!--T:2--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:3--&amp;gt;&lt;br /&gt;
To modify the configuration settings of the installation, you have to edit the optional settings. They can be found in the /application/config/&#039;&#039;&#039;config-defaults.php&#039;&#039;&#039;, which is located in the LimeSurvey root directory. The default settings of the standard installation can be found in config-defaults.php. Some of them can be overridden by using the [[Global settings]|global settings] dialog, while the others will have to be manually edited.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:69--&amp;gt;&lt;br /&gt;
{{Alert|If you want to change these settings, please do not change them in config-defaults.php, but copy the particular setting/line to /application/config/&#039;&#039;&#039;config.php&#039;&#039;&#039; in &amp;lt;nowiki&amp;gt;&#039;config&#039;=&amp;gt;array( )&amp;lt;/nowiki&amp;gt; and change it there. All the newly modified/introduced settings from the config.php file will overridde the default values from config-defaults.php.}}&lt;br /&gt;
&lt;br /&gt;
When an upgrade occurs, only the config-defaults.php settings are changed. Therefore, editing the config.php file will save your customized settings. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:70--&amp;gt;&lt;br /&gt;
To update/add the LimeSurvey settings in /application/&#039;&#039;&#039;config/config.php&#039;&#039;&#039;, you have to update the config array:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot; enclose=&amp;quot;pre&amp;quot;&amp;gt;&lt;br /&gt;
    &#039;config&#039;=&amp;gt;array(&lt;br /&gt;
        &#039;debug&#039;=&amp;gt;0,&lt;br /&gt;
        &#039;debugsql&#039;=&amp;gt;0,&lt;br /&gt;
        &#039;LimeSurveySetting&#039;=&amp;gt;&#039;New value&#039;, // Update default LimeSurvey config here&lt;br /&gt;
    )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Yii settings= &amp;lt;!--T:71--&amp;gt;&lt;br /&gt;
LimeSurvey uses the Yii framework, which has its own configuration parameters in the application/config/&#039;&#039;&#039;config.php&#039;&#039;&#039; file. You can also access some specific configuration settings of LimeSurvey via the Yii configuration.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:72--&amp;gt;&lt;br /&gt;
The Yii specific settings are set in the components array:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot; enclose=&amp;quot;pre&amp;quot;&amp;gt;&lt;br /&gt;
    &#039;components&#039; =&amp;gt; array(&lt;br /&gt;
        &#039;db&#039; =&amp;gt; array(&lt;br /&gt;
            ....&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;Specific settings&#039;=&amp;gt;array(&lt;br /&gt;
            ....&lt;br /&gt;
        ),&lt;br /&gt;
    ),&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Note|For more information about the Yii framework, please access the [http://www.yiiframework.com/doc-2.0/guide-index.html following link.]}}&lt;br /&gt;
&lt;br /&gt;
==Database settings== &amp;lt;!--T:73--&amp;gt;&lt;br /&gt;
The database settings are written to config.php by the installer file when you install LimeSurvey for the first time. If needed, you can update this part of the config.php file. Please remember that you do this at your own risk!&lt;br /&gt;
See also the [http://www.yiiframework.com/doc/blog/1.1/en/prototype.database#establishing-database-connection Yii documentation], and please remember that LimeSurvey supports only the following types of database: mysql, pgsql, dblib, mssql, and sqlsrv.&lt;br /&gt;
&lt;br /&gt;
==Session settings== &amp;lt;!--T:74--&amp;gt;&lt;br /&gt;
You can set some session parameters in config.php (check the two examples from below). You can uncomment/add the part needed in config.php. See the [http://www.yiiframework.com/doc/api/1.1/CHttpSession Yii Documentation] for other settings.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:75--&amp;gt;&lt;br /&gt;
If you use SSL (&#039;https&#039;) for your LimeSurvey installation, adding the following lines to your config.php will increase the security of the session:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot; enclose=&amp;quot;pre&amp;quot;&amp;gt;        // Set the cookie via SSL&lt;br /&gt;
        &#039;session&#039; =&amp;gt; array (&lt;br /&gt;
            &#039;cookieParams&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;secure&#039; =&amp;gt; true, // use SSL for cookies&lt;br /&gt;
                    &#039;httponly&#039; =&amp;gt; true // Cookies may not be used by other protocols - experimental&lt;br /&gt;
                ),&lt;br /&gt;
            ),&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:76--&amp;gt;&lt;br /&gt;
If you want to fix the domain for a cookie, use the following syntax in config.php:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot; enclose=&amp;quot;pre&amp;quot;&amp;gt;        // Set the domain for cookie&lt;br /&gt;
        &#039;session&#039; =&amp;gt; array (&lt;br /&gt;
            &#039;cookieParams&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;domain&#039; =&amp;gt; &#039;.example.org&#039;,&lt;br /&gt;
                ),&lt;br /&gt;
            ),&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Request settings== &amp;lt;!--T:77--&amp;gt;&lt;br /&gt;
The request settings are important, but the default settings are already optimized for LimeSurvey usage. To read more about them, see the [http://www.yiiframework.com/doc/api/1.1/CHttpRequest Yii Documentation].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:81--&amp;gt;&lt;br /&gt;
For example, the LimeSurvey request settings configuration may be modified in the following way (at your own risk) :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot; enclose=&amp;quot;pre&amp;quot;&amp;gt;        // Disable CSRF protection&lt;br /&gt;
        &#039;request&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;enableCsrfValidation&#039;=&amp;gt;false,    &lt;br /&gt;
            ),&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot; enclose=&amp;quot;pre&amp;quot;&amp;gt;        // Enforce a certain URL base &lt;br /&gt;
        &#039;request&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;hostInfo&#039; =&amp;gt; &#039;http://www.example.org/&#039;  &lt;br /&gt;
            ),&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot; enclose=&amp;quot;pre&amp;quot;&amp;gt;        // Set the cookie domain name for CSRF protection&lt;br /&gt;
        &#039;request&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;csrfCookie&#039; =&amp;gt; array( &#039;domain&#039; =&amp;gt; &#039;.example.com&#039; )&lt;br /&gt;
        ),&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:82--&amp;gt;&lt;br /&gt;
If you need to update only the url for token emails, set your [[Optional_settings#Advanced_path_settings|publicurl]] in your config.php file.&lt;br /&gt;
&lt;br /&gt;
==URL settings== &amp;lt;!--T:78--&amp;gt;&lt;br /&gt;
To change the default URL settings, update the urlManager:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot; enclose=&amp;quot;pre&amp;quot;&amp;gt;       // Use short URL&lt;br /&gt;
		&#039;urlManager&#039; =&amp;gt; array(&lt;br /&gt;
			&#039;urlFormat&#039; =&amp;gt; &#039;path&#039;,&lt;br /&gt;
			&#039;showScriptName&#039; =&amp;gt; false,&lt;br /&gt;
		),&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
You can also add .html after the survey id in the following way:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot; enclose=&amp;quot;pre&amp;quot;&amp;gt;       // Use short URL&lt;br /&gt;
		&#039;urlManager&#039; =&amp;gt; array(&lt;br /&gt;
			&#039;urlFormat&#039; =&amp;gt; &#039;path&#039;,&lt;br /&gt;
			&#039;rules&#039; =&amp;gt; array (&lt;br /&gt;
			    &#039;&amp;lt;sid:\d+&amp;gt;&#039; =&amp;gt; array(&#039;survey/index&#039;,&#039;urlSuffix&#039;=&amp;gt;&#039;.html&#039;,&#039;matchValue&#039;=&amp;gt;true),&lt;br /&gt;
			 ),&lt;br /&gt;
			&#039;showScriptName&#039; =&amp;gt; false,&lt;br /&gt;
		),&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
For more information, check the [http://www.yiiframework.com/doc/guide/1.1/en/topics.url Yii documentation].&lt;br /&gt;
&lt;br /&gt;
==Logging settings==&lt;br /&gt;
&lt;br /&gt;
Yii provides different solutions to generate logs. To find out more about them, check the [http://www.yiiframework.com/doc/guide/1.1/en/topics.logging logging special topic]. LimeSurvey uses &#039;1&#039; or &#039;2&#039; by default, which allows every web user to see the logs. You can create your own settings using Yii directly.&lt;br /&gt;
&lt;br /&gt;
For example, a quick solution to log errors and warnings in files is: &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot; enclose=&amp;quot;pre&amp;quot;&amp;gt;       // Log error&lt;br /&gt;
&#039;log&#039; =&amp;gt; array(&lt;br /&gt;
    &#039;routes&#039; =&amp;gt; array(&lt;br /&gt;
        &#039;fileError&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;class&#039; =&amp;gt; &#039;CFileLogRoute&#039;,&lt;br /&gt;
            &#039;levels&#039; =&amp;gt; &#039;warning, error&#039;,&lt;br /&gt;
        ),&lt;br /&gt;
    ),&lt;br /&gt;
),&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Hint|Text=The file is saved by default to &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;limesurvey/tmp/runtime/application.log&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;, which is located in the LimeSurvey root folder.}}&lt;br /&gt;
{{Alert|Yii uses runtime path. By default, the logs are web accessible. They may contain a lot of information from your server. It is better to use a directory that cannot be accessed via the web. You can set it in routes or by updating  the [[Optional settings#Yii settings#Runtime path|Runtime path]].}}.&lt;br /&gt;
&lt;br /&gt;
==Runtime path==&lt;br /&gt;
&lt;br /&gt;
[http://www.yiiframework.com/doc/guide/1.1/en/basics.convention#directory The runtime path] must be a readable and writable directory for the “web user”. However, the runtime path contains files with potential security information that are located in the public web access area. LimeSurvey collects these files in the temp directory of the LimeSurvey root directory. In order to eliminate the access to such important data, you can set the runtime path outside the public web access by editing the respective lines in the /application/config/config.php file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot; enclose=&amp;quot;pre&amp;quot;&amp;gt; &lt;br /&gt;
return array(&lt;br /&gt;
  &#039;components&#039; =&amp;gt; array(&lt;br /&gt;
    […]&lt;br /&gt;
    &#039;runtimePath&#039;=&amp;gt;&#039;/var/limesurvey/runtime/&#039;,&lt;br /&gt;
    &#039;config&#039;=&amp;gt;array(&lt;br /&gt;
    […]&lt;br /&gt;
    )&lt;br /&gt;
  )&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=General settings= &amp;lt;!--T:4--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:64--&amp;gt;&lt;br /&gt;
*&#039;&#039;&#039;sitename&#039;&#039;&#039;: Gives your survey site a name. This name will appear in the survey list overview and in the administration header. The default value is &#039;LimeSurvey&#039; and it can be overridden in the [[Global settings|global settings]] dialog or edited in config.php.&lt;br /&gt;
*&#039;&#039;&#039;siteadminemail:&#039;&#039;&#039; This is the default email address of the site administrator and it is used for system messages and contact options. This setting is used only as default value and can be overridden in the [[Global settings|global settings]] dialog.&lt;br /&gt;
*&#039;&#039;&#039;siteadminbounce:&#039;&#039;&#039; This is the email address where bounced emails will be sent to. This setting is used only as default value and can be  overridden by the [[Global settings|global settings]] dialog.&lt;br /&gt;
*&#039;&#039;&#039;siteadminname:&#039;&#039;&#039; The real name of the site administrator. This setting is used only as default value and can be overridden in the [[Global settings|global settings]] dialog).&lt;br /&gt;
*&#039;&#039;&#039;proxy_host_name:&#039;&#039;&#039; This is the host name of your proxy server (it has to be mentioned if you are behind a proxy and you want to update LimeSurvey using [[ComfortUpdate|ComfortUpdate]]).&lt;br /&gt;
*&#039;&#039;&#039;proxy_host_port:&#039;&#039;&#039; This is the port of your proxy server (it has to be mentioned if you are behind a proxy and you want to update LimeSurvey  using [[ComfortUpdate|ComfortUpdate]]).&lt;br /&gt;
&lt;br /&gt;
= Security= &amp;lt;!--T:5--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:65--&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;maxLoginAttempt&#039;&#039;&#039;: This is the number of attempts a user has to enter the correct password before he or she gets her or his IP address blocked/locked out. The default value is 3 and it can be modified from config.php. &lt;br /&gt;
* &#039;&#039;&#039;timeOutTime&#039;&#039;&#039;: If the user enters the password incorrectly for &amp;lt;maxLoginAttempt&amp;gt;, she or he gets locked out for &amp;lt;timeOutTime&amp;gt; seconds. The default value is 10 minutes and it can be modified from config.php.&lt;br /&gt;
* &#039;&#039;&#039;surveyPreview_require_Auth&#039;&#039;&#039;: Set to true by default. If you set this to &#039;false&#039;, any person can test your survey using the survey URL, without logging in to the administration panel and without having to activate the survey first. This setting is a default value and can be overridden in the [[Global settings|global settings]] dialog or edited in config.php.&lt;br /&gt;
* &#039;&#039;&#039;usercontrolSameGroupPolicy&#039;&#039;&#039;: Set to true by default. By default, non-admin users defined in the LimeSurvey management interface will only be able to see users they create or users that belongs to at least one same group. The default value can be overridden in the [[Global settings|global settings]] dialog or edited in config.php.&lt;br /&gt;
*&#039;&#039;&#039;filterxsshtml:&#039;&#039;&#039; This setting enables the filtering of suspicious html tags located within surveys, groups, and questions and answer texts in the administration interface. Leave this to &#039;false&#039; only if you absolutely trust the users you created for the administration of LimeSurvey and if you want to allow these users to be able to use Javascript, Flash Movies, etc. &amp;lt;span class=&amp;quot;warning&amp;quot;&amp;gt;The super admins never have their HTML filtered&amp;lt;/span&amp;gt;.  The default value can be overridden in the [[Global settings|global settings]] dialog or edited in config.php.&lt;br /&gt;
*&#039;&#039;&#039;demoMode:&#039;&#039;&#039; If this option is set to &#039;true&#039; in config.php, then LimeSurvey will go into demo mode. The demo mode changes the following things:&lt;br /&gt;
** Disables admin user&#039;s details and password changing;&lt;br /&gt;
** Disables the upload of files on the template editor;&lt;br /&gt;
** Disables sending e-mail invitations and reminders;&lt;br /&gt;
** Disables the creation of a database dump;&lt;br /&gt;
** Disables the ability to modify the following global settings: site name, default language, default HTML leditor mode, XSS filter.&lt;br /&gt;
&lt;br /&gt;
= Resources= &amp;lt;!--T:6--&amp;gt;&lt;br /&gt;
*&#039;&#039;&#039;sessionlifetime:&#039;&#039;&#039; Defines the time in seconds after which a survey session expires. It applies only if you are using database sessions. If you do use database sessions, change the parameter in config.php or override the default value from the [[Global settings|global settings]] dialog.&lt;br /&gt;
*&#039;&#039;&#039;memorylimit:&#039;&#039;&#039; This sets how much memory LimeSurvey can access. &#039;128 MB&#039; is the minimum (MB=Megabyte) recommended. If you receive time out errors or have problems generating statistics or exporting files, raise this limit to &#039;256 MB&#039; or higher. If your web server has set a higher limit in config.php, then this setting will be ignored. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:7--&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;warningbox&amp;quot;&amp;gt;&#039;&#039;&#039;Please bear in mind that such local settings can always be overruled by the changes done in the global settings dialog&#039;&#039;&#039;.&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:66--&amp;gt;&lt;br /&gt;
To increase the memory limit to 128M you could also try adding:&lt;br /&gt;
*memory_limit = 128M to your server&#039;s main php.ini file (recommended, if you have access)&lt;br /&gt;
*memory_limit = 128M to a php.ini file in the LimeSurvey root&lt;br /&gt;
*php_value memory_limit 128M in a .htaccess file in the LimeSurvey root&lt;br /&gt;
&lt;br /&gt;
=Appearance= &amp;lt;!--T:8--&amp;gt;&lt;br /&gt;
*&#039;&#039;&#039;dropdownthreshold&#039;&#039;&#039;{{ObsoleteIn|2.50}}: When &amp;quot;R&amp;quot; is selected for &amp;lt;code&amp;gt;$dropdowns&amp;lt;/code&amp;gt;, the administrator is allowed to set a maximum number of options that will be displayed as radio buttons, before converting back to a dropdown list. If there is a question that has a large number of options, displaying all of them at once as radio buttons can look unwieldy, and can become counter-intuitive to users. Setting this to a maximum of, say 25 (which is the default) means that large lists are easier to be used by the administrators for the survey participant.&lt;br /&gt;
*&#039;&#039;&#039;repeatheadings:&#039;&#039;&#039; With the Array type question, often you&#039;ll have a lot of subquestions, which - when displayed on screen - take up more than one page. This setting lets you decide how many subquestions should be displayed before repeating the header information for the question. A good setting for this is around 15. If you don&#039;t want the headings to repeat at all, set this to 0. This setting is overridden in the [[Global settings|global settings]] dialog {{NewIn|2.05}}.&lt;br /&gt;
*&#039;&#039;&#039;minrepeatheadings:&#039;&#039;&#039; The minimum number of remaining subquestions that are required before repeating the headings in Array questions. The default value is 3 and it can be edited in config.php. &lt;br /&gt;
*&#039;&#039;&#039;defaulttemplate:&#039;&#039;&#039; This setting specifies the default theme used for the &#039;public list&#039; of surveys. This setting can be overridden in the [[Global settings|global settings]] dialog or edited in config.php.&lt;br /&gt;
*&#039;&#039;&#039;defaulthtmleditormode:&#039;&#039;&#039; Sets the default mode for the integrated HTML editor. This setting can be overridden in the [[Global settings|global settings]] dialog or edited in config.php. The valid settings are:&lt;br /&gt;
** &#039;inline&#039; - Inline replacement of fields by an HTML editor. Slow but convenient and user friendly;&lt;br /&gt;
** &#039;popup&#039; - Adds an icon that runs the HTML editor in a popup if needed. Faster, but HTML code is displayed in the form;&lt;br /&gt;
** &#039;none&#039;-  No HTML editor;&lt;br /&gt;
*&#039;&#039;&#039;column_style:&#039;&#039;&#039; Defines how columns are rendered for survey answers when using [[QS:Display_columns|display_columns]]. It can be edited in the config.php file. The valid settings are: &lt;br /&gt;
** &#039;css&#039; - it uses one of the various CSS methods to create columns (see the template style sheet for details);&lt;br /&gt;
** &#039;ul&#039; - the columns are rendered as multiple floated unordered lists (default);&lt;br /&gt;
** &#039;table&#039; - it uses conventional-tables based layout;&lt;br /&gt;
** NULL - it disables the use of columns.&lt;br /&gt;
&lt;br /&gt;
=Language &amp;amp; time= &amp;lt;!--T:9--&amp;gt;&lt;br /&gt;
*&#039;&#039;&#039;defaultlang:&#039;&#039;&#039; This should be set to the default language to be used in your administration scripts, and also the default setting for language in the public survey list. This setting can be overridden in the [[Global settings|global settings]] dialog or edited in config.php.&lt;br /&gt;
*&#039;&#039;&#039;timeadjust:&#039;&#039;&#039; If your web server is in a different time zone to the location where your surveys will be based, put the difference between your server and your home time zone here. For example, I live in Australia, but I use a US web server. The web server is 14 hours behind my local time zone. So my setting here is &amp;quot;14&amp;quot;. In other words, it adds 14 hours to the web servers time. This setting is particularly important when surveys timestamp the responses. This setting can be overridden in the [[Global settings|global settings]] dialog or edited in config.php.&lt;br /&gt;
&lt;br /&gt;
=Survey behavior= &amp;lt;!--T:10--&amp;gt;&lt;br /&gt;
*&#039;&#039;&#039;deletenonvalues:&#039;&#039;&#039; Use this feature with caution. By default (a value of 1), irrelevant questions are NULLed in the database. This ensures that the data in your database is internally consistent. However, there are rare cases where you might want to hold onto irrelevant values, in which case you can set the value to 0. For example, you ask the person his gender, and he accidentally says &#039;female&#039; and then answers some female-specific questions (questions that are conditioned on being female, so are only relevant for women). Then, he realizes his mistake, backs up, sets the gender to &#039;male&#039;, and continues with the survey.  Now, the female-specific questions are irrelevant. If &amp;lt;code&amp;gt;$deletenonvalues==1&amp;lt;/code&amp;gt;, those irrelevant values will be cleared (NULLed) in the database. If &amp;lt;code&amp;gt;$deletenonvalues==0&amp;lt;/code&amp;gt;, his erroneous answers will not be deleted, so they will still be present in the database when you analyze it. &lt;br /&gt;
*&#039;&#039;&#039;shownoanswer:&#039;&#039;&#039; When a radio button/select type question that contains editable answers (i.e.: List, Array questions) is not mandatory and &#039;shownoanswer&#039; is set to 1, an additional &#039;No answer&#039; entry is shown - so that participants may choose to not answer the question. Some people prefer this not to be available. This setting can be overridden from the [[Global settings|global settings]] dialog or edited in config.php. Valid values are:&lt;br /&gt;
**&#039;0&#039;: No; &lt;br /&gt;
**&#039;1&#039;: Yes;&lt;br /&gt;
**&#039;2&#039;: The Survey admin can choose.  &lt;br /&gt;
*&#039;&#039;&#039;printanswershonorsconditions:&#039;&#039;&#039; This setting determines if the printanswers feature will display entries from questions that were hidden by conditions-branching (Default: 1 = hide answers from questions hidden by conditions).&lt;br /&gt;
*&#039;&#039;&#039;hide_groupdescr_allinone:&#039;&#039;&#039; This setting is relevant for all-in-one surveys using conditions . When this is set to &#039;true&#039;, the group name and description is hidden if all questions in the group are hidden. The default value is &#039;true&#039;  - hides group name and description when all questions in the group are hidden by conditions. It can be edited in config.php.&lt;br /&gt;
*&#039;&#039;&#039;showpopups:&#039;&#039;&#039;  Show popup messages if mandatory or conditional questions have not been answered correctly:&lt;br /&gt;
** &#039;1&#039;=Show popup message (default);&lt;br /&gt;
** &#039;0&#039;=Show message on page instead;&lt;br /&gt;
** &#039;-1&#039;=Do not show the message at all (in this case, users will still see the question-specific tips indicating which questions must be answered).&lt;br /&gt;
&lt;br /&gt;
=Development and debugging= &amp;lt;!--T:11--&amp;gt;&lt;br /&gt;
*&#039;&#039;&#039;debug:&#039;&#039;&#039; With this setting, you set the PHP error reporting to E_ALL. This means that every little notice, warning or error related to the script is shown. This setting should be only switched to &#039;1&#039; if you are trying to debug the application for any reason. If you are a developer, switch it to &#039;2&#039;. Don&#039;t switch it to &#039;1&#039; or &#039;2&#039; in production since it might cause path disclosure. The default value is &#039;0&#039; and it can be edited in config.php. &lt;br /&gt;
*&#039;&#039;&#039;debugsql:&#039;&#039;&#039; Activate this setting if you want to display all SQL queries executed for the script on the bottom of each page. Very useful for the optimization of the the number of queries. In order to activate it, change the default value to &#039;1&#039; from the config.php file.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:79--&amp;gt;&lt;br /&gt;
In the case in which you experience an error in the application, we strongly recommend to activate the debug setting in order to get a more detailed error that you can submit with the bug report:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:80--&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot; enclose=&amp;quot;pre&amp;quot;&amp;gt;&lt;br /&gt;
    &#039;config&#039;=&amp;gt;array(&lt;br /&gt;
        &#039;debug&#039;=&amp;gt;2,&lt;br /&gt;
        &#039;debugsql&#039;=&amp;gt;0,&lt;br /&gt;
    )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Email settings= &amp;lt;!--T:12--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:13--&amp;gt;&lt;br /&gt;
All the settings from below can be overridden in the [[Global settings|global settings]] dialog.&lt;br /&gt;
*&#039;&#039;&#039;emailmethod:&#039; This determines how email messages are being sent. The following options are available:&lt;br /&gt;
**&#039;mail:&#039; it uses internal PHP mailer;&lt;br /&gt;
**&#039;sendmail:&#039; it uses sendmail mailer;&lt;br /&gt;
**&#039;smtp:&#039; it uses SMTP relaying. Use this setting when you are running LimeSurvey on a host that is not your mail server.&lt;br /&gt;
*&#039;&#039;&#039;emailsmtphost:&#039; If you use &#039;smtp&#039; as &amp;lt;code&amp;gt;$emailmethod&amp;lt;/code&amp;gt;, then you have to put your SMTP-server here. If you are using Google mail you might have to add the port number like $emailsmtphost = &#039;smtp.gmail.com:465&#039;.&lt;br /&gt;
*&#039;emailsmtpuser:&#039; If your SMTP-server needs authentication then set this to your user name, otherwise it must be blank.&lt;br /&gt;
*&#039;emailsmtppassword:&#039; If your SMTP-server needs authentication then set this to your password, otherwise it must be blank.&lt;br /&gt;
*&#039;emailsmtpssl:&#039; Set this to &#039;ssl&#039; or &#039;tls&#039; to use SSL/TLS for SMTP connection.&lt;br /&gt;
*&#039;maxemails:&#039; When sending invitations or reminders to survey participants, this setting is used to determine how many emails can be sent in one bunch. Different web servers have different email capacities and if your script takes too long to send a bunch of emails, the script could time out and cause errors. Most web servers can send 100 emails at a time within the default 30 second time limit for a PHP script. If you get script timeout errors when sending large numbers of emails, reduce the number in this setting. Clicking the &#039;send email invitation&#039; button from the token control toolbar (not the button situated on the right of each token) sends the &amp;lt;maxemails&amp;gt; number of invitations, then it displays a list of the addresses of the recipients and a warning that &#039;&#039;there are more emails pending than could be sent in one batch. Continue sending emails by clicking below. There are ### emails still to be sent.&#039;&#039; and provides a &amp;quot;continue button&amp;quot; to proceed with the next batch. I.e., the user determines when to send the next batch after each batch gets emailed. It is not necessary to wait with this screen active. The admin could log out and come back at a later time to send the next batch of invites.&lt;br /&gt;
&lt;br /&gt;
= Statistics and response browsing= &amp;lt;!--T:14--&amp;gt;&lt;br /&gt;
*&#039;&#039;&#039;filterout_incomplete_answers:&#039;&#039;&#039; Control the default behavior of filtering incomplete answers when browsing or analyzing responses. For a discussion on incomplete responses see our [[Browsing survey results|browsing survey results wiki]]. Since these records can corrupt the statistics, an option is given to switch this filter on or off in several GUI forms. The parameter can be edited in the config.php. The following options are available:&lt;br /&gt;
**&#039;show&#039;: Allows you to visualize both complete and incomplete answers;&lt;br /&gt;
**&#039;filter&#039;: It shows only complete answers;&lt;br /&gt;
**&#039;incomplete&#039;: Show only incomplete answers.&lt;br /&gt;
*&#039;&#039;&#039;strip_query_from_referer_url&#039;&#039;&#039;: This setting determines if the referrer URL saves the parameter or not. The default value is &#039;false&#039; (in this case, the referrer URL saves all parameters). Alternatively, this value can be set to &#039;true&#039; and the parameter part of the referrer URL will be removed.&lt;br /&gt;
*&#039;&#039;&#039;showaggregateddata:&#039;&#039;&#039; when activated, additional statistical values such as the arithmetic mean and standard deviation are shown. Furthermore, the data is aggregated to get a faster overview. For example, results of scale 1+2 and 4+5 are added to have a general ranking like &amp;quot;good&amp;quot; (1/2), &amp;quot;average&amp;quot; (3) and &amp;quot;bad&amp;quot; (4/5). This only affects question types  &amp;quot;A&amp;quot; (5 point array) and &amp;quot;5&amp;quot; (5 point choice).&lt;br /&gt;
* &#039;&#039;&#039;PDF Export Settings:&#039;&#039;&#039; This feature activates PDF export for printable surveys and Print Answers. The PDF export function is totally experimental and the output is far from being perfect. Unfortunately, no support can be given at the moment - if you want to help to fix it, please get in touch with us.&lt;br /&gt;
**&#039;usepdfexport&#039;: Set &#039;0&#039; to disable and &#039;1&#039; to enable;&lt;br /&gt;
**&#039;pdfdefaultfont&#039;: It represents the default font that will be used by the pdf export function. The default value is &#039;auto&#039;. To change it, you have to set it to one of the [https://tcpdf.org/docs/fonts/ PDF core fonts]. &lt;br /&gt;
**&#039;alternatepdffontfile&#039;: It&#039;s an array with language keys and their corresponding font. The default font for each language can be replaced in the config.php file;&lt;br /&gt;
**&#039;pdffontsize&#039;: it shows the font size for normal texts; For the title of the survey, it is &amp;lt;pdffontsize&amp;gt;+4, while for the group title is &amp;lt;pdffontsize&amp;gt;+2. It can be edited in the config.php file or from the [Global settings|global settings]] dialog;&lt;br /&gt;
**&#039;notsupportlanguages&#039;: it includes a list with the languages for which no PDF font was found. The list includes Amharic (&#039;am&#039;), Sinhala (&#039;si&#039;), and Thai (&#039;th&#039;), and it can be found in the config-defaults.php file;&lt;br /&gt;
**&#039;pdforientation&#039;: Set &#039;L&#039; for Landscape or &#039;P&#039; for portrait format. It can be edited from the config.php file.&lt;br /&gt;
*&#039;&amp;quot;Graph setting&amp;quot;&#039;&lt;br /&gt;
**&#039;chartfontfile&#039;: Sets the font file name that is used to create the statistical charts. The file has to be located in the fonts directory, located in the LimeSurvey root folder. It can be edited in the config.php file;&lt;br /&gt;
**&#039;alternatechartfontfile&#039;: It&#039;s an array with language keys and their corresponding font. It can be edited in the config.php file.&lt;br /&gt;
*&#039;&#039;&#039;showsgqacode:&#039;&#039;&#039; This setting is used at the printable survey feature and defaults to &#039;false&#039;&#039;. If you set &#039;&#039;showsgqacode = &#039;true&#039;;&#039;&#039;, the IDs of each question - and answer if applicable - will be shown. These IDs match the column heading at the Lime_survey_12345 table, which holds the answer data for a certain survey. These IDs can be used for a code book for manual database queries.&lt;br /&gt;
&lt;br /&gt;
= [[LDAP settings]]= &amp;lt;!--T:15--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:16--&amp;gt;&lt;br /&gt;
As this is an extensive topic we have moved [[LDAP settings]] to [[LDAP settings|another page.]]&lt;br /&gt;
&lt;br /&gt;
= Authentication= &amp;lt;!--T:17--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:67--&amp;gt;&lt;br /&gt;
Starting with LimeSurvey 2.05, authentication will be handled by plugins. As a result, the information below might be outdated. See [[Plugins]] for most up to date information.&lt;br /&gt;
&lt;br /&gt;
== Authentication delegation to the webserver== &amp;lt;!--T:18--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:19--&amp;gt;&lt;br /&gt;
System administrators may want to have their &#039;&#039;&#039;survey administrators&#039;&#039;&#039; authenticated against a central authentication system (Active Directory, openLdap, Radius, ...) rather than using the internal LimeSurvey database. An easy way to do this is to setup your web server software to use this external authentication system, and then ask LimeSurvey to trust the user identity reported by the web server. In order to enable this feature, you have to:&lt;br /&gt;
* set &#039;&#039;&#039;auth_webserver&#039;&#039;&#039; to &#039;true&#039; in config.php;&lt;br /&gt;
* enable authentication from the web server side.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:20--&amp;gt;&lt;br /&gt;
Please note that:&lt;br /&gt;
* LimeSurvey will then bypass its own authentication process (by using the login name reported by the web server without asking for a password);&lt;br /&gt;
* this can only replace the LimeSurvey GUI authentication system, &#039;&#039;&#039;not the survey invitation system&#039;&#039;&#039; (participant interface).&lt;br /&gt;
&lt;br /&gt;
== Authentication delegation with no automatic user import== &amp;lt;!--T:21--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:22--&amp;gt;&lt;br /&gt;
Please note that &amp;lt;u&amp;gt;Authentication Delegation doesn&#039;t bypass the LimeSurvey authorization system by default&amp;lt;/u&amp;gt; - meaning that, even if you don&#039;t have to manage passwords in LimeSurvey, you still need to define the users in the LimeSurvey database and assign them the correct set of rights in order to let them access the administration panel.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:23--&amp;gt;&lt;br /&gt;
A user is then granted access to LimeSurvey if and only if:&lt;br /&gt;
* he has been authenticated to the web server;&lt;br /&gt;
* his login name is defined as a user in the LimeSurvey user database (the user is then granted the privileges of the user defined in the LimeSurvey user database).&lt;br /&gt;
&lt;br /&gt;
== Authentication delegation with automatic user import== &amp;lt;!--T:24--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:25--&amp;gt;&lt;br /&gt;
When managing a huge user database, it is sometimes easier to auto-import users in the LimeSurvey database:&lt;br /&gt;
*&#039;&#039;&#039;auth_webserver_autocreate_user&#039;&#039;&#039;: If set to &#039;true&#039;, LimeSurvey will try to auto-import users authenticated by the web server but not already in its users DB.&lt;br /&gt;
*&#039;&#039;&#039;auth_webserver_autocreate_profile&#039;&#039;&#039;: An array describing the default profile that will be assigned to the user, including the full (fake) name, email, and privileges.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:26--&amp;gt;&lt;br /&gt;
If you want to customize the user profile so that it matches the logged-in user, you&#039;ll have to develop a simple function called &#039;&#039;&#039;hook_get_autouserprofile&#039;&#039;&#039; - with this function you can retrieve from a central user account database (for instance, from a LDAP directory) the true full name, names, and email of a particular user. You can even customize his privileges on the system based on the groups he is allocated in the external database.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:27--&amp;gt;&lt;br /&gt;
The &#039;&#039;&#039;hook_get_auth_webserver_profile&#039;&#039;&#039; function takes the user login name as the only argument and can return:&lt;br /&gt;
* False or an empty array - in this case the user is denied access to LimeSurvey;&lt;br /&gt;
* an array containing all common userprofile entries as described in the &amp;lt;code&amp;gt;$WebserverAuth_autouserprofile&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/translate&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;function hook_get_auth_webserver_profile($user_name)&lt;br /&gt;
{&lt;br /&gt;
     // Retrieve user&#039;s data from your database backend (for instance LDAP) here&lt;br /&gt;
     ... get $user_name_from_backend&lt;br /&gt;
     ... get $user_email_from_backend&lt;br /&gt;
     ... get $user_lang_from_backend&lt;br /&gt;
     ... from groups defined in your backend set $user_admin_status_frombackend_0_or_1&lt;br /&gt;
     return Array(&lt;br /&gt;
                     &#039;full_name&#039; =&amp;gt; &amp;quot;$user_name_from_backend&amp;quot;,&lt;br /&gt;
                     &#039;email&#039; =&amp;gt; &amp;quot;$user_email_from_backend&amp;quot;,&lt;br /&gt;
                     &#039;lang&#039; =&amp;gt; &#039;$user_lang_from_backend&#039;,&lt;br /&gt;
                     &#039;htmleditormode&#039; =&amp;gt; &#039;inline&#039;,&lt;br /&gt;
                     &#039;templatelist&#039; =&amp;gt; &#039;default,basic,MyOrgTemplate&#039;,&lt;br /&gt;
                     &#039;create_survey&#039; =&amp;gt; 1,&lt;br /&gt;
                     &#039;create_user&#039; =&amp;gt; 0,&lt;br /&gt;
                     &#039;delete_user&#039; =&amp;gt; 0,&lt;br /&gt;
                     &#039;superadmin&#039; =&amp;gt; $user_admin_status_frombackend_0_or_1,&lt;br /&gt;
                     &#039;configurator&#039; =&amp;gt;0,&lt;br /&gt;
                     &#039;manage_template&#039; =&amp;gt; 0,&lt;br /&gt;
                     &#039;manage_label&#039; =&amp;gt; 0);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
     // If user should be denied access, return an empty array&lt;br /&gt;
&lt;br /&gt;
     // return Array();&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;translate&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Alert|The optionnal &#039;hook_get_auth_webserver_profile&#039; function is for advanced user usage only! For further details, please read the comments from the config-defaults.php file.}}&lt;br /&gt;
&lt;br /&gt;
== User name mapping== &amp;lt;!--T:52--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:53--&amp;gt;&lt;br /&gt;
In the case in which some users have an external user name that is different from their LimeSurvey user name, you may find useful to use a user name mapping. This is done in LimeSurvey by using the &#039;&#039;&#039;auth_webserver_user_map&#039;&#039;&#039; parameter. For instance, imagine you don&#039;t have an &#039;admin&#039; user name defined in your external authentication database. Then, in order to login to LimeSurvey as admin, you&#039;ll have to map your external user name (let&#039;s call it &#039;myname&#039;) to the admin login name in LimeSurvey. The corresponding setup is:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/translate&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&#039;config&#039;=&amp;gt;array(&lt;br /&gt;
...&lt;br /&gt;
&#039;auth_webserver_user_map&#039; =&amp;gt; array (&#039;myname&#039; =&amp;gt; &#039;admin&#039;);&lt;br /&gt;
)&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;translate&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:55--&amp;gt;&lt;br /&gt;
After a successful authentication with the &#039;myname&#039; login and web server password, you&#039;ll be directly authorized to use LimeSurvey as the &#039;admin&#039; user.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:56--&amp;gt;&lt;br /&gt;
This obviously has serious security implications, so use it with care, and please protect your config.php from write access by the web server.&lt;br /&gt;
&lt;br /&gt;
== Use one-time passwords== &amp;lt;!--T:57--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:59--&amp;gt;&lt;br /&gt;
A user can open the LimeSurvey login page at default.com/limesurvey/admin and type the username and the one-time password which was previously written into the users table (column one_time_pw) by an external application.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:60--&amp;gt;&lt;br /&gt;
This setting has to be turned on (&amp;lt;code&amp;gt;config[&#039;use_one_time_passwords&#039;] = true;&amp;lt;/code&amp;gt;) to enable the usage of one-time passwords (default = false). More information can be found in the [[Manage users#Use one-time passwords|&amp;quot;Manage Users&amp;quot; section]].&lt;br /&gt;
&lt;br /&gt;
= Advanced path settings= &amp;lt;!--T:61--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:62--&amp;gt;&lt;br /&gt;
*&#039;&#039;&#039;homeurl:&#039;&#039;&#039; This should be set to the URL location of your administration scripts. These are located in the /limesurvey/admin folder. This should be set to the WEB URL location - for example, &amp;quot;http://www.example.com/limesurvey/html/admin&amp;quot;. Don&#039;t add a trailing slash to this entry. The default setting in config.php attempts to detect the name of your server automatically using a php variable setting - &amp;lt;code&amp;gt;{$_SERVER&amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;&#039;SERVER_NAME&#039;]}&amp;lt;/code&amp;gt;. In most cases you can leave this and just modify the remainder of this string to match the directory name you have put the LimeSurvey scripts in.&lt;br /&gt;
*&#039;&#039;&#039;publicurl:&#039;&#039;&#039; This should be set to the URL location of your &#039;public scripts&#039;. The public scripts are those located in the &amp;quot;limesurvey&amp;quot; folder (or whatever name you gave to the directory that all the other scripts and directories are kept in). &#039;&#039;&#039;This settings is available in config.php and it is used when token emails are sent.&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;&#039;tempurl:&#039;&#039;&#039; This should be set to the URL location of your &amp;quot;/limesurvey/tmp&amp;quot; directory - or to a directory in which you would like LimeSurvey to use to store temporary files, including uploads. This directory must be set to read &amp;amp; write for your webserver (e.g. chmod 755). &lt;br /&gt;
*&#039;&#039;&#039;imagefiles:&#039;&#039;&#039; By default, you should leave this pointing to the URL location of /limesurvey/admin/images - where the images are initially installed. You may, however, prefer to move these images to another location/ If this is the case, point this to the URL directory where they are stored.&lt;br /&gt;
*&#039;&#039;&#039;homedir:&#039;&#039;&#039; This should be set to the physical disk location of your administration scripts - for example &amp;quot;/home/usr/htdocs/limesurvey/admin&amp;quot;. Don&#039;t add a trailing slash to this entry. The default setting in config.php attempts to detect the default root path of all your documents using the php variable setting  &amp;lt;code&amp;gt;{$_SERVER&amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;&#039;DOCUMENT_ROOT&#039;]}&amp;lt;/code&amp;gt;. In most cases you can leave this and just modify the remainder of this string to match the directory name you have put the LimeSurvey scripts in.&lt;br /&gt;
*&#039;&#039;&#039;publicdir:&#039;&#039;&#039; This should be set to the physical disk location of your &#039;public scripts&#039;.&lt;br /&gt;
*&#039;&#039;&#039;tempdir:&#039;&#039;&#039; This should be set to the physical disk location of your /limesurvey/tmp directory so that the script can read and write files.&lt;br /&gt;
*&#039;&#039;&#039;sCKEditorURL:&#039;&#039;&#039; url of the fckeditor script.&lt;br /&gt;
*&#039;&#039;&#039;fckeditexpandtoolbar:&#039;&#039;&#039; defines if the fckeditor toolbar should be opened by default.&lt;br /&gt;
*&#039;&#039;&#039;pdfexportdir:&#039;&#039;&#039; This is the directory with the tcpdf.php extensiontcpdf.php.&lt;br /&gt;
*&#039;&#039;&#039;pdffonts:&#039;&#039;&#039; This is the directory for the TCPDF fonts.&lt;br /&gt;
&amp;lt;/translate&amp;gt;&lt;/div&gt;</summary>
		<author><name>LimeAJ</name></author>
	</entry>
	<entry>
		<id>https://www.limesurvey.org/manual/index.php?title=Optional_settings&amp;diff=76438</id>
		<title>Optional settings</title>
		<link rel="alternate" type="text/html" href="https://www.limesurvey.org/manual/index.php?title=Optional_settings&amp;diff=76438"/>
		<updated>2017-08-25T19:56:00Z</updated>

		<summary type="html">&lt;p&gt;LimeAJ: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;languages /&amp;gt; &amp;lt;translate&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:63--&amp;gt;&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
The following section is addressed to those of you who would like to edit those configuration settings that could not be modified with the help of the GUI (Graphical User Interface) of the LimeSurvey installation. Please bear in mind that all the changes from the LimeSurvey root directory changes are done at your own risk. Nevertheless, in the case in which you are experiencing problems/need further guidance, join the [https://www.limesurvey.org/forum discussion forums] or the [irc://irc.freenode.net/limesurvey|IRC IRC channel] for help from the LimeSurvey community.&lt;br /&gt;
&lt;br /&gt;
=Introduction= &amp;lt;!--T:2--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:3--&amp;gt;&lt;br /&gt;
To modify the configuration settings of the installation, you have to edit the optional settings. They can be found in the /application/config/&#039;&#039;&#039;config-defaults.php&#039;&#039;&#039;, which is located in the LimeSurvey root directory. The default settings of the standard installation can be found in config-defaults.php. Some of them can be overridden by using the [[Global settings]|global settings] dialog, while the others will have to be manually edited.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:69--&amp;gt;&lt;br /&gt;
{{Alert|If you want to change these settings, please do not change them in config-defaults.php, but copy the particular setting/line to /application/config/&#039;&#039;&#039;config.php&#039;&#039;&#039; in &amp;lt;nowiki&amp;gt;&#039;config&#039;=&amp;gt;array( )&amp;lt;/nowiki&amp;gt; and change it there. All the newly modified/introduced settings from the config.php file will overridde the default values from config-defaults.php.}}&lt;br /&gt;
&lt;br /&gt;
When an upgrade occurs, only the config-defaults.php settings are changed. Therefore, editing the config.php file will save your customized settings. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:70--&amp;gt;&lt;br /&gt;
To update/add the LimeSurvey settings in /application/&#039;&#039;&#039;config/config.php&#039;&#039;&#039;, you have to update the config array:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot; enclose=&amp;quot;pre&amp;quot;&amp;gt;&lt;br /&gt;
    &#039;config&#039;=&amp;gt;array(&lt;br /&gt;
        &#039;debug&#039;=&amp;gt;0,&lt;br /&gt;
        &#039;debugsql&#039;=&amp;gt;0,&lt;br /&gt;
        &#039;LimeSurveySetting&#039;=&amp;gt;&#039;New value&#039;, // Update default LimeSurvey config here&lt;br /&gt;
    )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Yii settings= &amp;lt;!--T:71--&amp;gt;&lt;br /&gt;
LimeSurvey uses the Yii framework, which has its own configuration parameters in the application/config/&#039;&#039;&#039;config.php&#039;&#039;&#039; file. You can also access some specific configuration settings of LimeSurvey via the Yii configuration.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:72--&amp;gt;&lt;br /&gt;
The Yii specific settings are set in the components array:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot; enclose=&amp;quot;pre&amp;quot;&amp;gt;&lt;br /&gt;
    &#039;components&#039; =&amp;gt; array(&lt;br /&gt;
        &#039;db&#039; =&amp;gt; array(&lt;br /&gt;
            ....&lt;br /&gt;
        ),&lt;br /&gt;
        &#039;Specific settings&#039;=&amp;gt;array(&lt;br /&gt;
            ....&lt;br /&gt;
        ),&lt;br /&gt;
    ),&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Note|For more information about the Yii framework, please access the [http://www.yiiframework.com/doc-2.0/guide-index.html following link.]}}&lt;br /&gt;
&lt;br /&gt;
==Database settings== &amp;lt;!--T:73--&amp;gt;&lt;br /&gt;
The database settings are written to config.php by the installer file when you install LimeSurvey for the first time. If needed, you can update this part of the config.php file. Please remember that you do this at your own risk!&lt;br /&gt;
See also the [http://www.yiiframework.com/doc/blog/1.1/en/prototype.database#establishing-database-connection Yii documentation], and please remember that LimeSurvey supports only the following types of database: mysql, pgsql, dblib, mssql, and sqlsrv.&lt;br /&gt;
&lt;br /&gt;
==Session settings== &amp;lt;!--T:74--&amp;gt;&lt;br /&gt;
You can set some session parameters in config.php (check the two examples from below). You can uncomment/add the part needed in config.php. See the [http://www.yiiframework.com/doc/api/1.1/CHttpSession Yii Documentation] for other settings.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:75--&amp;gt;&lt;br /&gt;
If you use SSL (&#039;https&#039;) for your LimeSurvey installation, adding the following lines to your config.php will increase the security of the session:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot; enclose=&amp;quot;pre&amp;quot;&amp;gt;        // Set the cookie via SSL&lt;br /&gt;
        &#039;session&#039; =&amp;gt; array (&lt;br /&gt;
            &#039;cookieParams&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;secure&#039; =&amp;gt; true, // use SSL for cookies&lt;br /&gt;
                    &#039;httponly&#039; =&amp;gt; true // Cookies may not be used by other protocols - experimental&lt;br /&gt;
                ),&lt;br /&gt;
            ),&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:76--&amp;gt;&lt;br /&gt;
If you want to fix the domain for a cookie, use the following syntax in config.php:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot; enclose=&amp;quot;pre&amp;quot;&amp;gt;        // Set the domain for cookie&lt;br /&gt;
        &#039;session&#039; =&amp;gt; array (&lt;br /&gt;
            &#039;cookieParams&#039; =&amp;gt; array(&lt;br /&gt;
                    &#039;domain&#039; =&amp;gt; &#039;.example.org&#039;,&lt;br /&gt;
                ),&lt;br /&gt;
            ),&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Request settings== &amp;lt;!--T:77--&amp;gt;&lt;br /&gt;
The request settings are important, but the default settings are already optimized for LimeSurvey usage. To read more about them, see the [http://www.yiiframework.com/doc/api/1.1/CHttpRequest Yii Documentation].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:81--&amp;gt;&lt;br /&gt;
For example, the LimeSurvey request settings configuration may be modified in the following way (at your own risk) :&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot; enclose=&amp;quot;pre&amp;quot;&amp;gt;        // Disable CSRF protection&lt;br /&gt;
        &#039;request&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;enableCsrfValidation&#039;=&amp;gt;false,    &lt;br /&gt;
            ),&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot; enclose=&amp;quot;pre&amp;quot;&amp;gt;        // Enforce a certain URL base &lt;br /&gt;
        &#039;request&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;hostInfo&#039; =&amp;gt; &#039;http://www.example.org/&#039;  &lt;br /&gt;
            ),&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot; enclose=&amp;quot;pre&amp;quot;&amp;gt;        // Set the cookie domain name for CSRF protection&lt;br /&gt;
        &#039;request&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;csrfCookie&#039; =&amp;gt; array( &#039;domain&#039; =&amp;gt; &#039;.example.com&#039; )&lt;br /&gt;
        ),&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:82--&amp;gt;&lt;br /&gt;
If you need to update only the url for token emails, set your [[Optional_settings#Advanced_path_settings|publicurl]] in your config.php file.&lt;br /&gt;
&lt;br /&gt;
==URL settings== &amp;lt;!--T:78--&amp;gt;&lt;br /&gt;
To change the default URL settings, update the urlManager:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot; enclose=&amp;quot;pre&amp;quot;&amp;gt;       // Use short URL&lt;br /&gt;
		&#039;urlManager&#039; =&amp;gt; array(&lt;br /&gt;
			&#039;urlFormat&#039; =&amp;gt; &#039;path&#039;,&lt;br /&gt;
			&#039;showScriptName&#039; =&amp;gt; false,&lt;br /&gt;
		),&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
You can also add .html after the survey id in the following way:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot; enclose=&amp;quot;pre&amp;quot;&amp;gt;       // Use short URL&lt;br /&gt;
		&#039;urlManager&#039; =&amp;gt; array(&lt;br /&gt;
			&#039;urlFormat&#039; =&amp;gt; &#039;path&#039;,&lt;br /&gt;
			&#039;rules&#039; =&amp;gt; array (&lt;br /&gt;
			    &#039;&amp;lt;sid:\d+&amp;gt;&#039; =&amp;gt; array(&#039;survey/index&#039;,&#039;urlSuffix&#039;=&amp;gt;&#039;.html&#039;,&#039;matchValue&#039;=&amp;gt;true),&lt;br /&gt;
			 ),&lt;br /&gt;
			&#039;showScriptName&#039; =&amp;gt; false,&lt;br /&gt;
		),&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
For more information, check the [http://www.yiiframework.com/doc/guide/1.1/en/topics.url Yii documentation].&lt;br /&gt;
&lt;br /&gt;
==Logging settings==&lt;br /&gt;
&lt;br /&gt;
Yii provides different solutions to generate logs. To find out more about them, check the [http://www.yiiframework.com/doc/guide/1.1/en/topics.logging logging special topic]. LimeSurvey uses &#039;1&#039; or &#039;2&#039; by default, which allows every web user to see the logs. You can create your own settings using Yii directly.&lt;br /&gt;
&lt;br /&gt;
For example, a quick solution to log errors and warnings in files is: &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot; enclose=&amp;quot;pre&amp;quot;&amp;gt;       // Log error&lt;br /&gt;
&#039;log&#039; =&amp;gt; array(&lt;br /&gt;
    &#039;routes&#039; =&amp;gt; array(&lt;br /&gt;
        &#039;fileError&#039; =&amp;gt; array(&lt;br /&gt;
            &#039;class&#039; =&amp;gt; &#039;CFileLogRoute&#039;,&lt;br /&gt;
            &#039;levels&#039; =&amp;gt; &#039;warning, error&#039;,&lt;br /&gt;
        ),&lt;br /&gt;
    ),&lt;br /&gt;
),&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Hint|Text=The file is saved by default to &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;limesurvey/tmp/runtime/application.log&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt;, which is located in the LimeSurvey root folder.}}&lt;br /&gt;
{{Alert|Yii uses runtime path. By default, the logs are web accessible. They may contain a lot of information from your server. It is better to use a directory that cannot be accessed via the web. You can set it in routes or by updating  the [[Optional settings#Yii settings#Runtime path|Runtime path]].}}.&lt;br /&gt;
&lt;br /&gt;
==Runtime path==&lt;br /&gt;
&lt;br /&gt;
[http://www.yiiframework.com/doc/guide/1.1/en/basics.convention#directory The runtime path] must be a readable and writable directory for the “web user”. However, the runtime path contains files with potential security information that are located in the public web access area. LimeSurvey collects these files in the temp directory of the LimeSurvey root directory. In order to eliminate the access to such important data, you can set the runtime path outside the public web access by editing the respective lines in the /application/config/config.php file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot; enclose=&amp;quot;pre&amp;quot;&amp;gt; &lt;br /&gt;
return array(&lt;br /&gt;
  &#039;components&#039; =&amp;gt; array(&lt;br /&gt;
    […]&lt;br /&gt;
    &#039;runtimePath&#039;=&amp;gt;&#039;/var/limesurvey/runtime/&#039;,&lt;br /&gt;
    &#039;config&#039;=&amp;gt;array(&lt;br /&gt;
    […]&lt;br /&gt;
    )&lt;br /&gt;
  )&lt;br /&gt;
)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=General settings= &amp;lt;!--T:4--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:64--&amp;gt;&lt;br /&gt;
*&#039;&#039;&#039;sitename&#039;&#039;&#039;: Gives your survey site a name. This name will appear in the survey list overview and in the administration header. The default value is &#039;LimeSurvey&#039; and it can be overridden in the [[Global settings|global settings]] dialog or edited in config.php.&lt;br /&gt;
*&#039;&#039;&#039;siteadminemail:&#039;&#039;&#039; This is the default email address of the site administrator and it is used for system messages and contact options. This setting is used only as default value and can be overridden in the [[Global settings|global settings]] dialog.&lt;br /&gt;
*&#039;&#039;&#039;siteadminbounce:&#039;&#039;&#039; This is the email address where bounced emails will be sent to. This setting is used only as default value and can be  overridden by the [[Global settings|global settings]] dialog.&lt;br /&gt;
*&#039;&#039;&#039;siteadminname:&#039;&#039;&#039; The real name of the site administrator. This setting is used only as default value and can be overridden in the [[Global settings|global settings]] dialog).&lt;br /&gt;
*&#039;&#039;&#039;proxy_host_name:&#039;&#039;&#039; This is the host name of your proxy server (it has to be mentioned if you are behind a proxy and you want to update LimeSurvey using [[ComfortUpdate|ComfortUpdate]]).&lt;br /&gt;
*&#039;&#039;&#039;proxy_host_port:&#039;&#039;&#039; This is the port of your proxy server (it has to be mentioned if you are behind a proxy and you want to update LimeSurvey  using [[ComfortUpdate|ComfortUpdate]]).&lt;br /&gt;
&lt;br /&gt;
= Security= &amp;lt;!--T:5--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:65--&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;maxLoginAttempt&#039;&#039;&#039;: This is the number of attempts a user has to enter the correct password before he or she gets her or his IP address blocked/locked out. The default value is 3 and it can be modified from config.php. &lt;br /&gt;
* &#039;&#039;&#039;timeOutTime&#039;&#039;&#039;: If the user enters the password incorrectly for &amp;lt;maxLoginAttempt&amp;gt;, she or he gets locked out for &amp;lt;timeOutTime&amp;gt; seconds. The default value is 10 minutes and it can be modified from config.php.&lt;br /&gt;
* &#039;&#039;&#039;surveyPreview_require_Auth&#039;&#039;&#039;: Set to true by default. If you set this to &#039;false&#039;, any person can test your survey using the survey URL, without logging in to the administration panel and without having to activate the survey first. This setting is a default value and can be overridden in the [[Global settings|global settings]] dialog or edited in config.php.&lt;br /&gt;
* &#039;&#039;&#039;usercontrolSameGroupPolicy&#039;&#039;&#039;: Set to true by default. By default, non-admin users defined in the LimeSurvey management interface will only be able to see users they create or users that belongs to at least one same group. The default value can be overridden in the [[Global settings|global settings]] dialog or edited in config.php.&lt;br /&gt;
*&#039;&#039;&#039;filterxsshtml:&#039;&#039;&#039; This setting enables the filtering of suspicious html tags located within surveys, groups, and questions and answer texts in the administration interface. Leave this to &#039;false&#039; only if you absolutely trust the users you created for the administration of LimeSurvey and if you want to allow these users to be able to use Javascript, Flash Movies, etc. &amp;lt;span class=&amp;quot;warning&amp;quot;&amp;gt;The super admins never have their HTML filtered&amp;lt;/span&amp;gt;.  The default value can be overridden in the [[Global settings|global settings]] dialog or edited in config.php.&lt;br /&gt;
*&#039;&#039;&#039;demoMode:&#039;&#039;&#039; If this option is set to &#039;true&#039; in config.php, then LimeSurvey will go into demo mode. The demo mode changes the following things:&lt;br /&gt;
** Disables admin user&#039;s details and password changing;&lt;br /&gt;
** Disables the upload of files on the template editor;&lt;br /&gt;
** Disables sending e-mail invitations and reminders;&lt;br /&gt;
** Disables the creation of a database dump;&lt;br /&gt;
** Disables the ability to modify the following global settings: site name, default language, default HTML leditor mode, XSS filter.&lt;br /&gt;
&lt;br /&gt;
= Resources= &amp;lt;!--T:6--&amp;gt;&lt;br /&gt;
*&#039;&#039;&#039;sessionlifetime:&#039;&#039;&#039; Defines the time in seconds after which a survey session expires. It applies only if you are using database sessions. If you do use database sessions, change the parameter in config.php or override the default value from the [[Global settings|global settings]] dialog.&lt;br /&gt;
*&#039;&#039;&#039;memorylimit:&#039;&#039;&#039; This sets how much memory LimeSurvey can access. &#039;128 MB&#039; is the minimum (MB=Megabyte) recommended. If you receive time out errors or have problems generating statistics or exporting files, raise this limit to &#039;256 MB&#039; or higher. If your web server has set a higher limit in config.php, then this setting will be ignored. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:7--&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;warningbox&amp;quot;&amp;gt;&#039;&#039;&#039;Please bear in mind that such local settings can always be overruled by the changes done in the global settings dialog&#039;&#039;&#039;.&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:66--&amp;gt;&lt;br /&gt;
To increase the memory limit to 128M you could also try adding:&lt;br /&gt;
*memory_limit = 128M to your server&#039;s main php.ini file (recommended, if you have access)&lt;br /&gt;
*memory_limit = 128M to a php.ini file in the LimeSurvey root&lt;br /&gt;
*php_value memory_limit 128M in a .htaccess file in the LimeSurvey root&lt;br /&gt;
&lt;br /&gt;
=Appearance= &amp;lt;!--T:8--&amp;gt;&lt;br /&gt;
*&#039;&#039;&#039;dropdownthreshold&#039;&#039;&#039;{{ObsoleteIn|2.50}}: When &amp;quot;R&amp;quot; is selected for &amp;lt;code&amp;gt;$dropdowns&amp;lt;/code&amp;gt;, the administrator is allowed to set a maximum number of options that will be displayed as radio buttons, before converting back to a dropdown list. If there is a question that has a large number of options, displaying all of them at once as radio buttons can look unwieldy, and can become counter-intuitive to users. Setting this to a maximum of, say 25 (which is the default) means that large lists are easier to be used by the administrators for the survey participant.&lt;br /&gt;
*&#039;&#039;&#039;repeatheadings:&#039;&#039;&#039; With the Array type question, often you&#039;ll have a lot of subquestions, which - when displayed on screen - take up more than one page. This setting lets you decide how many subquestions should be displayed before repeating the header information for the question. A good setting for this is around 15. If you don&#039;t want the headings to repeat at all, set this to 0. This setting is overridden in the [[Global settings|global settings]] dialog {{NewIn|2.05}}.&lt;br /&gt;
*&#039;&#039;&#039;minrepeatheadings:&#039;&#039;&#039; The minimum number of remaining subquestions that are required before repeating the headings in Array questions. The default value is 3 and it can be edited in config.php. &lt;br /&gt;
*&#039;&#039;&#039;defaulttemplate:&#039;&#039;&#039; This setting specifies the default theme used for the &#039;public list&#039; of surveys. This setting can be overridden in the [[Global settings|global settings]] dialog or edited in config.php.&lt;br /&gt;
*&#039;&#039;&#039;defaulthtmleditormode:&#039;&#039;&#039; Sets the default mode for the integrated HTML editor. This setting can be overridden in the [[Global settings|global settings]] dialog or edited in config.php. The valid settings are:&lt;br /&gt;
** &#039;inline&#039; - Inline replacement of fields by an HTML editor. Slow but convenient and user friendly;&lt;br /&gt;
** &#039;popup&#039; - Adds an icon that runs the HTML editor in a popup if needed. Faster, but HTML code is displayed in the form;&lt;br /&gt;
** &#039;none&#039;-  No HTML editor;&lt;br /&gt;
*&#039;&#039;&#039;column_style:&#039;&#039;&#039; Defines how columns are rendered for survey answers when using [[QS:Display_columns|display_columns]]. It can be edited in the config.php file. The valid settings are: &lt;br /&gt;
** &#039;css&#039; - it uses one of the various CSS methods to create columns (see the template style sheet for details);&lt;br /&gt;
** &#039;ul&#039; - the columns are rendered as multiple floated unordered lists (default);&lt;br /&gt;
** &#039;table&#039; - it uses conventional-tables based layout;&lt;br /&gt;
** NULL - it disables the use of columns.&lt;br /&gt;
&lt;br /&gt;
=Language &amp;amp; time= &amp;lt;!--T:9--&amp;gt;&lt;br /&gt;
*&#039;&#039;&#039;defaultlang:&#039;&#039;&#039; This should be set to the default language to be used in your administration scripts, and also the default setting for language in the public survey list. This setting can be overridden in the [[Global settings|global settings]] dialog or edited in config.php.&lt;br /&gt;
*&#039;&#039;&#039;timeadjust:&#039;&#039;&#039; If your web server is in a different time zone to the location where your surveys will be based, put the difference between your server and your home time zone here. For example, I live in Australia, but I use a US web server. The web server is 14 hours behind my local time zone. So my setting here is &amp;quot;14&amp;quot;. In other words, it adds 14 hours to the web servers time. This setting is particularly important when surveys timestamp the responses. This setting can be overridden in the [[Global settings|global settings]] dialog or edited in config.php.&lt;br /&gt;
&lt;br /&gt;
=Survey behavior= &amp;lt;!--T:10--&amp;gt;&lt;br /&gt;
*&#039;&#039;&#039;deletenonvalues:&#039;&#039;&#039; Use this feature with caution. By default (a value of 1), irrelevant questions are NULLed in the database. This ensures that the data in your database is internally consistent. However, there are rare cases where you might want to hold onto irrelevant values, in which case you can set the value to 0. For example, you ask the person his gender, and he accidentally says &#039;female&#039; and then answers some female-specific questions (questions that are conditioned on being female, so are only relevant for women). Then, he realizes his mistake, backs up, sets the gender to &#039;male&#039;, and continues with the survey.  Now, the female-specific questions are irrelevant. If &amp;lt;code&amp;gt;$deletenonvalues==1&amp;lt;/code&amp;gt;, those irrelevant values will be cleared (NULLed) in the database. If &amp;lt;code&amp;gt;$deletenonvalues==0&amp;lt;/code&amp;gt;, his erroneous answers will not be deleted, so they will still be present in the database when you analyze it. &lt;br /&gt;
*&#039;&#039;&#039;shownoanswer:&#039;&#039;&#039; When a radio button/select type question that contains editable answers (i.e.: List, Array questions) is not mandatory and &#039;shownoanswer&#039; is set to 1, an additional &#039;No answer&#039; entry is shown - so that participants may choose to not answer the question. Some people prefer this not to be available. This setting can be overridden from the [[Global settings|global settings]] dialog or edited in config.php. Valid values are:&lt;br /&gt;
**&#039;0&#039;: No; &lt;br /&gt;
**&#039;1&#039;: Yes;&lt;br /&gt;
**&#039;2&#039;: The Survey admin can choose.  &lt;br /&gt;
*&#039;&#039;&#039;printanswershonorsconditions:&#039;&#039;&#039; This setting determines if the printanswers feature will display entries from questions that were hidden by conditions-branching (Default: 1 = hide answers from questions hidden by conditions).&lt;br /&gt;
*&#039;&#039;&#039;hide_groupdescr_allinone:&#039;&#039;&#039; This setting is relevant for all-in-one surveys using conditions . When this is set to &#039;true&#039;, the group name and description is hidden if all questions in the group are hidden. The default value is &#039;true&#039;  - hides group name and description when all questions in the group are hidden by conditions. It can be edited in config.php.&lt;br /&gt;
*&#039;&#039;&#039;showpopups:&#039;&#039;&#039;  Show popup messages if mandatory or conditional questions have not been answered correctly:&lt;br /&gt;
** &#039;1&#039;=Show popup message (default);&lt;br /&gt;
** &#039;0&#039;=Show message on page instead;&lt;br /&gt;
** &#039;-1&#039;=Do not show the message at all (in this case, users will still see the question-specific tips indicating which questions must be answered).&lt;br /&gt;
&lt;br /&gt;
=Development and debugging= &amp;lt;!--T:11--&amp;gt;&lt;br /&gt;
*&#039;&#039;&#039;debug:&#039;&#039;&#039; With this setting, you set the PHP error reporting to E_ALL. This means that every little notice, warning or error related to the script is shown. This setting should be only switched to &#039;1&#039; if you are trying to debug the application for any reason. If you are a developer, switch it to &#039;2&#039;. Don&#039;t switch it to &#039;1&#039; or &#039;2&#039; in production since it might cause path disclosure. The default value is &#039;0&#039; and it can be edited in config.php. &lt;br /&gt;
*&#039;&#039;&#039;debugsql:&#039;&#039;&#039; Activate this setting if you want to display all SQL queries executed for the script on the bottom of each page. Very useful for the optimization of the the number of queries. In order to activate it, change the default value to &#039;1&#039; from the config.php file.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:79--&amp;gt;&lt;br /&gt;
In the case in which you experience an error in the application, we strongly recommend to activate the debug setting in order to get a more detailed error that you can submit with the bug report:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:80--&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot; enclose=&amp;quot;pre&amp;quot;&amp;gt;&lt;br /&gt;
    &#039;config&#039;=&amp;gt;array(&lt;br /&gt;
        &#039;debug&#039;=&amp;gt;2,&lt;br /&gt;
        &#039;debugsql&#039;=&amp;gt;0,&lt;br /&gt;
    )&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Email settings= &amp;lt;!--T:12--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:13--&amp;gt;&lt;br /&gt;
All the settings from below can be overridden in the [[Global settings|global settings]] dialog.&lt;br /&gt;
*&#039;&#039;&#039;emailmethod:&#039; This determines how email messages are being sent. The following options are available:&lt;br /&gt;
**&#039;mail:&#039; it uses internal PHP mailer;&lt;br /&gt;
**&#039;sendmail:&#039; it uses sendmail mailer;&lt;br /&gt;
**&#039;smtp:&#039; it uses SMTP relaying. Use this setting when you are running LimeSurvey on a host that is not your mail server.&lt;br /&gt;
*&#039;&#039;&#039;emailsmtphost:&#039; If you use &#039;smtp&#039; as &amp;lt;code&amp;gt;$emailmethod&amp;lt;/code&amp;gt;, then you have to put your SMTP-server here. If you are using Google mail you might have to add the port number like $emailsmtphost = &#039;smtp.gmail.com:465&#039;.&lt;br /&gt;
*&#039;emailsmtpuser:&#039; If your SMTP-server needs authentication then set this to your user name, otherwise it must be blank.&lt;br /&gt;
*&#039;emailsmtppassword:&#039; If your SMTP-server needs authentication then set this to your password, otherwise it must be blank.&lt;br /&gt;
*&#039;emailsmtpssl:&#039; Set this to &#039;ssl&#039; or &#039;tls&#039; to use SSL/TLS for SMTP connection.&lt;br /&gt;
*&#039;maxemails:&#039; When sending invitations or reminders to survey participants, this setting is used to determine how many emails can be sent in one bunch. Different web servers have different email capacities and if your script takes too long to send a bunch of emails, the script could time out and cause errors. Most web servers can send 100 emails at a time within the default 30 second time limit for a PHP script. If you get script timeout errors when sending large numbers of emails, reduce the number in this setting. Clicking the &#039;send email invitation&#039; button from the token control toolbar (not the button situated on the right of each token) sends the &amp;lt;maxemails&amp;gt; number of invitations, then it displays a list of the addresses of the recipients and a warning that &#039;&#039;there are more emails pending than could be sent in one batch. Continue sending emails by clicking below. There are ### emails still to be sent.&#039;&#039; and provides a &amp;quot;continue button&amp;quot; to proceed with the next batch. I.e., the user determines when to send the next batch after each batch gets emailed. It is not necessary to wait with this screen active. The admin could log out and come back at a later time to send the next batch of invites.&lt;br /&gt;
&lt;br /&gt;
= Statistics and response browsing= &amp;lt;!--T:14--&amp;gt;&lt;br /&gt;
*&#039;&#039;&#039;filterout_incomplete_answers:&#039;&#039;&#039; Control the default behavior of filtering incomplete answers when browsing or analyzing responses. For a discussion on incomplete responses see our [[Browsing survey results|browsing survey results wiki]]. Since these records can corrupt the statistics, an option is given to switch this filter on or off in several GUI forms. The parameter can be edited in the config.php. The following options are available:&lt;br /&gt;
**&#039;show&#039;: Allows you to visualize both complete and incomplete answers;&lt;br /&gt;
**&#039;filter&#039;: It shows only complete answers;&lt;br /&gt;
**&#039;incomplete&#039;: Show only incomplete answers.&lt;br /&gt;
*&#039;&#039;&#039;strip_query_from_referer_url&#039;&#039;&#039;: This setting determines if the referrer URL saves the parameter or not. The default value is &#039;false&#039; (in this case, the referrer URL saves all parameters). Alternatively, this value can be set to &#039;true&#039; and the parameter part of the referrer URL will be removed.&lt;br /&gt;
*&#039;&#039;&#039;showaggregateddata:&#039;&#039;&#039; when activated, additional statistical values such as the arithmetic mean and standard deviation are shown. Furthermore, the data is aggregated to get a faster overview. For example, results of scale 1+2 and 4+5 are added to have a general ranking like &amp;quot;good&amp;quot; (1/2), &amp;quot;average&amp;quot; (3) and &amp;quot;bad&amp;quot; (4/5). This only affects question types  &amp;quot;A&amp;quot; (5 point array) and &amp;quot;5&amp;quot; (5 point choice).&lt;br /&gt;
* &#039;&#039;&#039;PDF Export Settings:&#039;&#039;&#039; This feature activates PDF export for printable surveys and Print Answers. The PDF export function is totally experimental and the output is far from being perfect. Unfortunately, no support can be given at the moment - if you want to help to fix it, please get in touch with us.&lt;br /&gt;
**&#039;usepdfexport&#039;: Set &#039;0&#039; to disable and &#039;1&#039; to enable;&lt;br /&gt;
**&#039;pdfdefaultfont&#039;: It represents the default font that will be used by the pdf export function. The default value is &#039;auto&#039;. To change it, you have to set it to one of the [https://tcpdf.org/docs/fonts/ PDF core fonts]. &lt;br /&gt;
**&#039;alternatepdffontfile&#039;: It&#039;s an array with language keys and their corresponding font. The default font for each language can be replaced in the config.php file;&lt;br /&gt;
**&#039;pdffontsize&#039;: it shows the font size for normal texts; For the title of the survey, it is &amp;lt;pdffontsize&amp;gt;+4, while for the group title is &amp;lt;pdffontsize&amp;gt;+2. It can be edited in the config.php file or from the [Global settings|global settings]] dialog;&lt;br /&gt;
**&#039;notsupportlanguages&#039;: it includes a list with the languages for which no PDF font was found. The list includes Amharic (&#039;am&#039;), Sinhala (&#039;si&#039;), and Thai (&#039;th&#039;), and it can be found in the config-defaults.php file;&lt;br /&gt;
**&#039;pdforientation&#039;: Set &#039;L&#039; for Landscape or &#039;P&#039; for portrait format. It can be edited from the config.php file.&lt;br /&gt;
*&#039;&amp;quot;Graph setting&amp;quot;&#039;&lt;br /&gt;
**&#039;chartfontfile&#039;: Sets the font file name that is used to create the statistical charts. The file has to be located in the fonts directory, located in the LimeSurvey root folder. It can be edited in the config.php file;&lt;br /&gt;
**&#039;alternatechartfontfile&#039;: It&#039;s an array with language keys and their corresponding font. It can be edited in the config.php file.&lt;br /&gt;
*&#039;&#039;&#039;showsgqacode:&#039;&#039;&#039; This setting is used at the printable survey feature and defaults to &#039;false&#039;&#039;. If you set &#039;&#039;showsgqacode = &#039;true&#039;;&#039;&#039;, the IDs of each question - and answer if applicable - will be shown. These IDs match the column heading at the Lime_survey_12345 table, which holds the answer data for a certain survey. These IDs can be used for a code book for manual database queries.&lt;br /&gt;
&lt;br /&gt;
= [[LDAP settings]]= &amp;lt;!--T:15--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:16--&amp;gt;&lt;br /&gt;
As this is an extensive topic we have moved [[LDAP settings]] to [[LDAP settings|another page.]]&lt;br /&gt;
&lt;br /&gt;
= Authentication= &amp;lt;!--T:17--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:67--&amp;gt;&lt;br /&gt;
Starting with LimeSurvey 2.05, authentication will be handled by plugins. As a result, the information below might be outdated. See [[Plugins]] for most up to date information.&lt;br /&gt;
&lt;br /&gt;
== Authentication delegation to the webserver== &amp;lt;!--T:18--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:19--&amp;gt;&lt;br /&gt;
System administrators may want to have their &#039;&#039;&#039;survey administrators&#039;&#039;&#039; authenticated against a central authentication system (Active Directory, openLdap, Radius, ...) rather than using the internal LimeSurvey database. An easy way to do this is to setup your web server software to use this external authentication system, and then ask LimeSurvey to trust the user identity reported by the web server. In order to enable this feature, you have to:&lt;br /&gt;
* set &#039;&#039;&#039;auth_webserver&#039;&#039;&#039; to &#039;true&#039; in config.php;&lt;br /&gt;
* enable authentication from the web server side.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:20--&amp;gt;&lt;br /&gt;
Please note that:&lt;br /&gt;
* LimeSurvey will then bypass its own authentication process (by using the login name reported by the web server without asking for a password);&lt;br /&gt;
* this can only replace the LimeSurvey GUI authentication system, &#039;&#039;&#039;not the survey invitation system&#039;&#039;&#039; (participant interface).&lt;br /&gt;
&lt;br /&gt;
== Authentication delegation with no automatic user import== &amp;lt;!--T:21--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:22--&amp;gt;&lt;br /&gt;
Please note that &amp;lt;u&amp;gt;Authentication Delegation doesn&#039;t bypass the LimeSurvey authorization system by default&amp;lt;/u&amp;gt; - meaning that, even if you don&#039;t have to manage passwords in LimeSurvey, you still need to define the users in the LimeSurvey database and assign them the correct set of rights in order to let them access the administration panel.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:23--&amp;gt;&lt;br /&gt;
A user is then granted access to LimeSurvey if and only if:&lt;br /&gt;
* he has been authenticated to the web server;&lt;br /&gt;
* his login name is defined as a user in the LimeSurvey user database (the user is then granted the privileges of the user defined in the LimeSurvey user database).&lt;br /&gt;
&lt;br /&gt;
== Authentication delegation with automatic user import== &amp;lt;!--T:24--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:25--&amp;gt;&lt;br /&gt;
When managing a huge user database, it is sometimes easier to auto-import users in the LimeSurvey database:&lt;br /&gt;
*&#039;&#039;&#039;auth_webserver_autocreate_user&#039;&#039;&#039;: If set to &#039;true&#039;, LimeSurvey will try to auto-import users authenticated by the web server but not already in its users DB.&lt;br /&gt;
*&#039;&#039;&#039;auth_webserver_autocreate_profile&#039;&#039;&#039;: An array describing the default profile that will be assigned to the user, including the full (fake) name, email, and privileges.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:26--&amp;gt;&lt;br /&gt;
If you want to customize the user profile so that it matches the logged-in user, you&#039;ll have to develop a simple function called &#039;&#039;&#039;hook_get_autouserprofile&#039;&#039;&#039; - with this function you can retrieve from a central user account database (for instance, from a LDAP directory) the true full name, names, and email of a particular user. You can even customize his privileges on the system based on the groups he is allocated in the external database.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:27--&amp;gt;&lt;br /&gt;
The &#039;&#039;&#039;hook_get_auth_webserver_profile&#039;&#039;&#039; function takes the user login name as the only argument and can return:&lt;br /&gt;
* False or an empty array - in this case the user is denied access to LimeSurvey;&lt;br /&gt;
* an array containing all common userprofile entries as described in the &amp;lt;code&amp;gt;$WebserverAuth_autouserprofile&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/translate&amp;gt;&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;function hook_get_auth_webserver_profile($user_name)&lt;br /&gt;
{&lt;br /&gt;
     // Retrieve user&#039;s data from your database backend (for instance LDAP) here&lt;br /&gt;
     ... get $user_name_from_backend&lt;br /&gt;
     ... get $user_email_from_backend&lt;br /&gt;
     ... get $user_lang_from_backend&lt;br /&gt;
     ... from groups defined in your backend set $user_admin_status_frombackend_0_or_1&lt;br /&gt;
     return Array(&lt;br /&gt;
                     &#039;full_name&#039; =&amp;gt; &amp;quot;$user_name_from_backend&amp;quot;,&lt;br /&gt;
                     &#039;email&#039; =&amp;gt; &amp;quot;$user_email_from_backend&amp;quot;,&lt;br /&gt;
                     &#039;lang&#039; =&amp;gt; &#039;$user_lang_from_backend&#039;,&lt;br /&gt;
                     &#039;htmleditormode&#039; =&amp;gt; &#039;inline&#039;,&lt;br /&gt;
                     &#039;templatelist&#039; =&amp;gt; &#039;default,basic,MyOrgTemplate&#039;,&lt;br /&gt;
                     &#039;create_survey&#039; =&amp;gt; 1,&lt;br /&gt;
                     &#039;create_user&#039; =&amp;gt; 0,&lt;br /&gt;
                     &#039;delete_user&#039; =&amp;gt; 0,&lt;br /&gt;
                     &#039;superadmin&#039; =&amp;gt; $user_admin_status_frombackend_0_or_1,&lt;br /&gt;
                     &#039;configurator&#039; =&amp;gt;0,&lt;br /&gt;
                     &#039;manage_template&#039; =&amp;gt; 0,&lt;br /&gt;
                     &#039;manage_label&#039; =&amp;gt; 0);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
     // If user should be denied access, return an empty array&lt;br /&gt;
&lt;br /&gt;
     // return Array();&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;translate&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Alert|The optionnal &#039;hook_get_auth_webserver_profile&#039; function is for advanced user usage only! For further details, please read the comments from the config-defaults.php file.}}&lt;br /&gt;
&lt;br /&gt;
== User name mapping== &amp;lt;!--T:52--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:53--&amp;gt;&lt;br /&gt;
In the case in which some users have an external user name that is different from their LimeSurvey user name, you may find useful to use a user name mapping. This is done in LimeSurvey by using the &#039;&#039;&#039;auth_webserver_user_map&#039;&#039;&#039; parameter. For instance, imagine you don&#039;t have an &#039;admin&#039; user name defined in your external authentication database. Then, in order to login to LimeSurvey as admin, you&#039;ll have to map your external user name (let&#039;s call it &#039;myname&#039;) to the admin login name in LimeSurvey. The corresponding setup is:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/translate&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&#039;config&#039;=&amp;gt;array(&lt;br /&gt;
...&lt;br /&gt;
&#039;auth_webserver_user_map&#039; =&amp;gt; array (&#039;myname&#039; =&amp;gt; &#039;admin&#039;);&lt;br /&gt;
)&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;translate&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:55--&amp;gt;&lt;br /&gt;
After a successful authentication with the &#039;myname&#039; login and web server password, you&#039;ll be directly authorized to use LimeSurvey as the &#039;admin&#039; user.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:56--&amp;gt;&lt;br /&gt;
This obviously has serious security implications, so use it with care, and please protect your config.php from write access by the web server.&lt;br /&gt;
&lt;br /&gt;
== Use one-time passwords== &amp;lt;!--T:57--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:59--&amp;gt;&lt;br /&gt;
A user can open the LimeSurvey login page at default.com/limesurvey/admin and type the username and the one-time password which was previously written into the users table (column one_time_pw) by an external application.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:60--&amp;gt;&lt;br /&gt;
This setting has to be turned on (&amp;lt;code&amp;gt;config[&#039;use_one_time_passwords&#039;] = true;&amp;lt;/code&amp;gt;) to enable the usage of one-time passwords (default = false). More information can be found in the [[Manage users#Use one-time passwords|&amp;quot;Manage Users&amp;quot; section]].&lt;br /&gt;
&lt;br /&gt;
= Advanced path settings= &amp;lt;!--T:61--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:62--&amp;gt;&lt;br /&gt;
*&#039;&#039;&#039;homeurl:&#039;&#039;&#039; This should be set to the URL location of your administration scripts. These are located in the /limesurvey/admin folder. This should be set to the WEB URL location - for example, &amp;quot;http://www.example.com/limesurvey/html/admin&amp;quot;. Don&#039;t add a trailing slash to this entry. The default setting in config.php attempts to detect the name of your server automatically using a php variable setting - &amp;lt;code&amp;gt;{$_SERVER&amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;&#039;SERVER_NAME&#039;]}&amp;lt;/code&amp;gt;. In most cases you can leave this and just modify the remainder of this string to match the directory name you have put the LimeSurvey scripts in.&lt;br /&gt;
*&#039;&#039;&#039;publicurl:&#039;&#039;&#039; This should be set to the URL location of your &#039;public scripts&#039;. The public scripts are those located in the &amp;quot;limesurvey&amp;quot; folder (or whatever name you gave to the directory that all the other scripts and directories are kept in). &#039;&#039;&#039;This settings is available in config.php and it is used when token emails are sent.&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;&#039;tempurl:&#039;&#039;&#039; This should be set to the URL location of your &amp;quot;/limesurvey/tmp&amp;quot; directory - or to a directory in which you would like LimeSurvey to use to store temporary files, including uploads. This directory must be set to read &amp;amp; write for your webserver (e.g. chmod 755). &lt;br /&gt;
*&#039;&#039;&#039;imagefiles:&#039;&#039;&#039; By default, you should leave this pointing to the URL location of /limesurvey/admin/images - where the images are initially installed. You may, however, prefer to move these images to another location/ If this is the case, point this to the URL directory where they are stored.&lt;br /&gt;
*&#039;&#039;&#039;homedir:&#039;&#039;&#039; This should be set to the physical disk location of your administration scripts - for example &amp;quot;/home/usr/htdocs/limesurvey/admin&amp;quot;. Don&#039;t add a trailing slash to this entry. The default setting in config.php attempts to detect the default root path of all your documents using the php variable setting  &amp;lt;code&amp;gt;{$_SERVER&amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;&#039;DOCUMENT_ROOT&#039;]}&amp;lt;/code&amp;gt;. In most cases you can leave this and just modify the remainder of this string to match the directory name you have put the LimeSurvey scripts in.&lt;br /&gt;
*&#039;&#039;&#039;publicdir:&#039;&#039;&#039; This should be set to the physical disk location of your &#039;public scripts&#039;.&lt;br /&gt;
*&#039;&#039;&#039;tempdir:&#039;&#039;&#039; This should be set to the physical disk location of your /limesurvey/tmp directory so that the script can read and write files.&lt;br /&gt;
*&#039;&#039;&#039;sCKEditorURL:&#039;&#039;&#039; url of the fckeditor script.&lt;br /&gt;
*&#039;&#039;&#039;fckeditexpandtoolbar:&#039;&#039;&#039; defines if the fckeditor toolbar should be opened by default.&lt;br /&gt;
*&#039;&#039;&#039;pdfexportdir:&#039;&#039;&#039; This is the directory with the tcpdf.php extensiontcpdf.php.&lt;br /&gt;
*&#039;&#039;&#039;pdffonts:&#039;&#039;&#039; This is the directory for the TCPDF fonts.&lt;br /&gt;
&amp;lt;/translate&amp;gt;&lt;/div&gt;</summary>
		<author><name>LimeAJ</name></author>
	</entry>
	<entry>
		<id>https://www.limesurvey.org/manual/index.php?title=RemoteControl_2_API&amp;diff=76437</id>
		<title>RemoteControl 2 API</title>
		<link rel="alternate" type="text/html" href="https://www.limesurvey.org/manual/index.php?title=RemoteControl_2_API&amp;diff=76437"/>
		<updated>2017-08-25T15:56:14Z</updated>

		<summary type="html">&lt;p&gt;LimeAJ: /* PHP Example */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
=Introduction=&lt;br /&gt;
&lt;br /&gt;
LimeSurvey RemoteControl 2 is a XML-RPC/JSON-RPC based web service available in LimeSurvey 2.0 or more recent which offers &#039;&#039;&#039;various [https://api.limesurvey.org/classes/remotecontrol_handle.html API functions]&#039;&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
LSRC2 makes it possible for developers to control specific functionality of LimeSurvey from any other application, without being restricted to PHP as a programming language.&lt;br /&gt;
&lt;br /&gt;
The following features are planned:&lt;br /&gt;
* start a predefined survey (change titles and things)&lt;br /&gt;
* add predefined groups or questions&lt;br /&gt;
* activate the survey, restrict it to start and endtime&lt;br /&gt;
* make it closed,&lt;br /&gt;
* add participant data/tokens when you need them&lt;br /&gt;
* return the unused tokens to the main application&lt;br /&gt;
* get a fieldmap for a survey,&lt;br /&gt;
* invite or remind the participants of your survey&lt;br /&gt;
&lt;br /&gt;
...and much more&lt;br /&gt;
&lt;br /&gt;
==Requirements==&lt;br /&gt;
* libXML installed&lt;br /&gt;
&lt;br /&gt;
=Setup=&lt;br /&gt;
&lt;br /&gt;
== How to configure LSRC2==&lt;br /&gt;
&lt;br /&gt;
In a default LimeSurvey installation LSRC2 is disabled. In order to use LSRC2 you must first enable the service, and then adjust the settings to suit your needs. To enable LSRC2 login to the LimeSurvey administration, go to [[Global settings]], choose the tab &#039;Interfaces&#039; and select one of the two RPC services (XML-RPC or JSON-RPC) service.&lt;br /&gt;
&lt;br /&gt;
== Security==&lt;br /&gt;
&lt;br /&gt;
LSRC2 uses the same security measures as the normal administration login. That means that the permission set of the used username and password is the same as if you would login in the administration with that user/password. Also LSRC2 is protected against brute-force password cracking - like the normal administration login.&lt;br /&gt;
&lt;br /&gt;
=How to use LSRC2=&lt;br /&gt;
&lt;br /&gt;
The basic LSRC2 URL is: http://&amp;lt;your_domain&amp;gt;/&amp;lt;your_limesurvey_dir&amp;gt;/index.php/admin/remotecontrol&lt;br /&gt;
&lt;br /&gt;
LSRC2 fully complies to the [http://www.xmlrpc.com/ XML-RPC specification] and JSON-RPC version 1 specifications. We recommend in general to use JSON-RPC because it is well tested and has a much smaller footprint than XML-RPC.&lt;br /&gt;
&lt;br /&gt;
LSRC2 offers a lot of functions. Please check the automatically generated [http://api.limesurvey.org/classes/remotecontrol_handle.html API Documentation].&lt;br /&gt;
LSRC2 offers the following functions:&lt;br /&gt;
&lt;br /&gt;
== Sessions ==&lt;br /&gt;
&lt;br /&gt;
=== get_session_key ===&lt;br /&gt;
&lt;br /&gt;
Using this function you can create a new XML/JSON-RPC session key. This is mandatory for all following LSRC2 function calls.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=php&amp;gt;&lt;br /&gt;
function get_session_key(string $username, string $password)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Return on success&#039;&#039;&#039;: (string) session key.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Return on error&#039;&#039;&#039;:  for protocol-level errors (invalid format etc), an error message. For invalid username and password, returns a null error and the result body contains a &#039;status&#039; name-value pair with the error message.&lt;br /&gt;
&lt;br /&gt;
=== release_session_key ===&lt;br /&gt;
&lt;br /&gt;
Using this function you can close a previously opened XML-RPC/JSON-RPC session.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=php&amp;gt;&lt;br /&gt;
function release_session_key(string $sSessionKey)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Parameter !! Description&lt;br /&gt;
|-&lt;br /&gt;
| sSessionKey || Auth credentials&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Return&#039;&#039;&#039;: Always &#039;OK&#039; (string)&lt;br /&gt;
&lt;br /&gt;
== Other functions ==&lt;br /&gt;
&lt;br /&gt;
{{Alert|For all other function , you have to refer to the [http://api.limesurvey.org/classes/remotecontrol_handle.html online API ] . If your LimeSurvey version is outdated, you can publish your API and look at it directly.}}&lt;br /&gt;
&lt;br /&gt;
= Example and helper =&lt;br /&gt;
&lt;br /&gt;
== PHP Example ==&lt;br /&gt;
&lt;br /&gt;
To include JSON-RPC in your application, you can write an application using the light-weight jsonRPCClient from the [https://github.com/weberhofer/jsonrpcphp jsonrpcphp Github repository]. The library can also get included by composer calling&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
composer require weberhofer/jsonrpcphp&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
or by inclusion of the following lines in your composer.json file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=javascript&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
    &amp;quot;require&amp;quot;: {&lt;br /&gt;
        &amp;quot;weberhofer/jsonrpcphp&amp;quot;: &amp;quot;~2&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is a example how to connect to limesurvey:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
// without composer this line can be used&lt;br /&gt;
// require_once &#039;path/to/your/rpcclient/jsonRPCClient.php&#039;;&lt;br /&gt;
// with composer support just add the autoloader&lt;br /&gt;
include_once &#039;vendor/autoload.php&#039;;&lt;br /&gt;
&lt;br /&gt;
define( &#039;LS_BASEURL&#039;, &#039;https://localhost/limesurvey/&#039;);  // adjust this one to your actual LimeSurvey URL&lt;br /&gt;
define( &#039;LS_USER&#039;, &#039;rpcuser&#039; );&lt;br /&gt;
define( &#039;LS_PASSWORD&#039;, &#039;mypassword&#039; );&lt;br /&gt;
&lt;br /&gt;
// the survey to process&lt;br /&gt;
$survey_id=374699;&lt;br /&gt;
&lt;br /&gt;
// instantiate a new client&lt;br /&gt;
$myJSONRPCClient = new \org\jsonrpcphp\JsonRPCClient( LS_BASEURL.&#039;/admin/remotecontrol&#039; );&lt;br /&gt;
&lt;br /&gt;
// receive session key&lt;br /&gt;
$sessionKey= $myJSONRPCClient-&amp;gt;get_session_key( LS_USER, LS_PASSWORD );&lt;br /&gt;
&lt;br /&gt;
// receive all ids and info of groups belonging to a given survey&lt;br /&gt;
$groups = $myJSONRPCClient-&amp;gt;list_groups( $sessionKey, $survey_id );&lt;br /&gt;
print_r($groups, null );&lt;br /&gt;
&lt;br /&gt;
// release the session key&lt;br /&gt;
$myJSONRPCClient-&amp;gt;release_session_key( $sessionKey );&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== JAVA example ==&lt;br /&gt;
To decode and code your json calls you can use the library gson as you can see in the following example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
import java.io.IOException;&lt;br /&gt;
import java.io.UnsupportedEncodingException;&lt;br /&gt;
&lt;br /&gt;
import org.apache.http.HttpEntity;&lt;br /&gt;
import org.apache.http.HttpResponse;&lt;br /&gt;
import org.apache.http.client.methods.HttpPost;&lt;br /&gt;
import org.apache.http.entity.StringEntity;&lt;br /&gt;
import org.apache.http.impl.client.DefaultHttpClient;&lt;br /&gt;
import org.apache.http.util.EntityUtils;&lt;br /&gt;
&lt;br /&gt;
import com.google.gson.JsonElement;&lt;br /&gt;
import com.google.gson.JsonObject;&lt;br /&gt;
import com.google.gson.JsonParser;&lt;br /&gt;
&lt;br /&gt;
public class TestHttpClient {&lt;br /&gt;
	&lt;br /&gt;
    public static String parse(String jsonLine) {&lt;br /&gt;
	 JsonElement jelement = new JsonParser().parse(jsonLine);&lt;br /&gt;
	 JsonObject  jobject = jelement.getAsJsonObject();&lt;br /&gt;
	 String result = jobject.get(&amp;quot;result&amp;quot;).getAsString();&lt;br /&gt;
	 return result;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	&lt;br /&gt;
    public static void main(String[] args) throws UnsupportedEncodingException {&lt;br /&gt;
      DefaultHttpClient client = new DefaultHttpClient();          &lt;br /&gt;
         &lt;br /&gt;
      HttpPost post = new HttpPost(&amp;quot;https://PATH_OF_YOUR_SERVER/index.php/admin/remotecontrol&amp;quot;);&lt;br /&gt;
      post.setHeader(&amp;quot;Content-type&amp;quot;, &amp;quot;application/json&amp;quot;);&lt;br /&gt;
      post.setEntity( new StringEntity(&amp;quot;{\&amp;quot;method\&amp;quot;: \&amp;quot;get_session_key\&amp;quot;, \&amp;quot;params\&amp;quot;: [\&amp;quot;YOUR_USERNAME\&amp;quot;, \&amp;quot;YOUR_PASSWORD\&amp;quot; ], \&amp;quot;id\&amp;quot;: 1}&amp;quot;));&lt;br /&gt;
      try {&lt;br /&gt;
        HttpResponse response = client.execute(post);&lt;br /&gt;
        if(response.getStatusLine().getStatusCode() == 200){&lt;br /&gt;
            HttpEntity entity = response.getEntity();&lt;br /&gt;
            String sessionKey = parse(EntityUtils.toString(entity));&lt;br /&gt;
            post.setEntity( new StringEntity(&amp;quot;{\&amp;quot;method\&amp;quot;: \&amp;quot;list_groups\&amp;quot;, \&amp;quot;params\&amp;quot;: [ \&amp;quot;&amp;quot;+sessionKey+&amp;quot;\&amp;quot;, \&amp;quot;ID_SURVEY\&amp;quot; ], \&amp;quot;id\&amp;quot;: 1}&amp;quot;));&lt;br /&gt;
            response = client.execute(post);&lt;br /&gt;
            if(response.getStatusLine().getStatusCode() == 200){&lt;br /&gt;
                entity = response.getEntity();&lt;br /&gt;
                System.out.println(EntityUtils.toString(entity));&lt;br /&gt;
                }&lt;br /&gt;
           }&lt;br /&gt;
       &lt;br /&gt;
       &lt;br /&gt;
      } catch (IOException e) {&lt;br /&gt;
        e.printStackTrace();&lt;br /&gt;
      }&lt;br /&gt;
    }}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Python example and glue ==&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/TaiSHiNet/lime-py-api LimeSurvey API - Python 2 glue]&lt;br /&gt;
* [https://github.com/lindsay-stevens/limesurveyrc2api LimeSurvey API - Basic client library in Python 3]. Includes tests. Listed on Pypi: pip install limesurveyrc2api&lt;br /&gt;
&lt;br /&gt;
The following code runs with Python 2 and requires some adaptation to work with Python 3.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
import urllib&lt;br /&gt;
import urllib2&lt;br /&gt;
import json&lt;br /&gt;
import sys&lt;br /&gt;
# There is an generic json-rpc implemantation in Python but it dose not work for me in this case so I worte Some functions &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
        &lt;br /&gt;
def get_session_key():&lt;br /&gt;
    req = urllib2.Request(url=&#039;https://myurl/index.php/admin/remotecontrol&#039;,\&lt;br /&gt;
                          data=&#039;{\&amp;quot;method\&amp;quot;:\&amp;quot;get_session_key\&amp;quot;,\&amp;quot;params\&amp;quot;:[\&amp;quot;admin\&amp;quot;,\&amp;quot;mypassword\&amp;quot;],\&amp;quot;id\&amp;quot;:1}&#039;)&lt;br /&gt;
    req.add_header(&#039;content-type&#039;, &#039;application/json&#039;)&lt;br /&gt;
    req.add_header(&#039;connection&#039;, &#039;Keep-Alive&#039;)&lt;br /&gt;
    try:&lt;br /&gt;
        f = urllib2.urlopen(req)&lt;br /&gt;
        myretun = f.read()&lt;br /&gt;
        #print myretun&lt;br /&gt;
        j=json.loads(myretun)&lt;br /&gt;
        return j[&#039;result&#039;]&lt;br /&gt;
    except :&lt;br /&gt;
        e = sys.exc_info()[0]&lt;br /&gt;
        print ( &amp;quot;&amp;lt;p&amp;gt;Error: %s&amp;lt;/p&amp;gt;&amp;quot; % e )&lt;br /&gt;
		&lt;br /&gt;
def get_question_properties(skey,QuestionID):&lt;br /&gt;
    req = urllib2.Request(url=&#039;https://myurl/index.php/admin/remotecontrol&#039;,\&lt;br /&gt;
                          data=&#039;{\&amp;quot;method\&amp;quot;:\&amp;quot;get_question_properties\&amp;quot;,\&amp;quot;params\&amp;quot;:[\&amp;quot;&#039;+skey+&#039;\&amp;quot;,&#039;+QuestionID&lt;br /&gt;
                                    +&#039;,[\&amp;quot;gid\&amp;quot;,\&amp;quot;type\&amp;quot;,\&amp;quot;help\&amp;quot;,\&amp;quot;language\&amp;quot;,\&amp;quot;sid\&amp;quot;,\&amp;quot;question_order\&amp;quot;,\&amp;quot;question\&amp;quot;,\&amp;quot;subquestions\&amp;quot;]],\&amp;quot;id\&amp;quot;: 1}&#039;)&lt;br /&gt;
&lt;br /&gt;
    req.add_header(&#039;content-type&#039;, &#039;application/json&#039;)&lt;br /&gt;
    req.add_header(&#039;connection&#039;, &#039;Keep-Alive&#039;)&lt;br /&gt;
    try:&lt;br /&gt;
        f = urllib2.urlopen(req)&lt;br /&gt;
        myretun = f.read()&lt;br /&gt;
        #print myretun&lt;br /&gt;
        j=json.loads(myretun)&lt;br /&gt;
        return j[&#039;result&#039;]&lt;br /&gt;
    except :&lt;br /&gt;
        e = sys.exc_info()[0]&lt;br /&gt;
        print ( &amp;quot;&amp;lt;p&amp;gt;Error: %s&amp;lt;/p&amp;gt;&amp;quot; % e )&lt;br /&gt;
&lt;br /&gt;
		&lt;br /&gt;
def release_session_key(relkey):&lt;br /&gt;
    req = urllib2.Request(url=&#039;https://myurl/index.php/admin/remotecontrol&#039;,\&lt;br /&gt;
                          data=&#039;{\&amp;quot;method\&amp;quot;:\&amp;quot;release_session_key\&amp;quot;,\&amp;quot;params\&amp;quot;:[\&amp;quot;&#039;+relkey+&#039;\&amp;quot;],\&amp;quot;id\&amp;quot;:1}&#039;)&lt;br /&gt;
    req.add_header(&#039;content-type&#039;, &#039;application/json&#039;)&lt;br /&gt;
    req.add_header(&#039;connection&#039;, &#039;Keep-Alive&#039;)&lt;br /&gt;
    try:&lt;br /&gt;
        f = urllib2.urlopen(req)&lt;br /&gt;
        myretun = f.read()&lt;br /&gt;
        #print myretun&lt;br /&gt;
        j=json.loads(myretun)&lt;br /&gt;
        return j[&#039;result&#039;]&lt;br /&gt;
    except :&lt;br /&gt;
        e = sys.exc_info()[0]&lt;br /&gt;
        print ( &amp;quot;&amp;lt;p&amp;gt;Error: %s&amp;lt;/p&amp;gt;&amp;quot; % e )&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def export_responses2(skey,sid):&lt;br /&gt;
    req = urllib2.Request(url=&#039;https://myurl/index.php/admin/remotecontrol&#039;,\&lt;br /&gt;
                          data=&#039;{\&amp;quot;method\&amp;quot;:\&amp;quot;export_responses\&amp;quot;,\&amp;quot;params\&amp;quot;:[\&amp;quot;&#039;+skey+&#039;\&amp;quot;,\&amp;quot;&#039;+sid+&#039;\&amp;quot;,\&amp;quot;csv\&amp;quot;,\&amp;quot;de\&amp;quot;,\&amp;quot;full\&amp;quot;],\&lt;br /&gt;
&amp;quot;id\&amp;quot;: 1}&#039;)&lt;br /&gt;
    req.add_header(&#039;content-type&#039;, &#039;application/json&#039;)&lt;br /&gt;
    req.add_header(&#039;connection&#039;, &#039;Keep-Alive&#039;)&lt;br /&gt;
    try:&lt;br /&gt;
        f = urllib2.urlopen(req)&lt;br /&gt;
        myretun = f.read()&lt;br /&gt;
        #print myretun&lt;br /&gt;
        j=json.loads(myretun)&lt;br /&gt;
        return j[&#039;result&#039;]&lt;br /&gt;
    except :&lt;br /&gt;
        e = sys.exc_info()[0]&lt;br /&gt;
        print ( &amp;quot;&amp;lt;p&amp;gt;Error: %s&amp;lt;/p&amp;gt;&amp;quot; % e )		&lt;br /&gt;
&lt;br /&gt;
		&lt;br /&gt;
mykey=get_session_key()&lt;br /&gt;
print export_responses2(mykey,&#039;566237&#039;).decode(&#039;base64&#039;)&lt;br /&gt;
get_question_properties(mykey,&#039;574&#039;)&lt;br /&gt;
print release_session_key(mykey)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== NodeJS example ==&lt;br /&gt;
&lt;br /&gt;
This script require request, you can include easily with the command &lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;&lt;br /&gt;
npm install request&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is a example how to connect to limesurvey:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
var request = require(&#039;request&#039;);&lt;br /&gt;
&lt;br /&gt;
//******GLOBAL***************&lt;br /&gt;
var SESSIONKEY=&amp;quot;&amp;quot;;&lt;br /&gt;
var options = {&lt;br /&gt;
  url: &amp;quot;https://xxxxxxxxxxxxxxxx/index.php/admin/remotecontrol&amp;quot;,&lt;br /&gt;
  method: &amp;quot;POST&amp;quot;,&lt;br /&gt;
  headers: {&lt;br /&gt;
    &#039;user-agent&#039;: &#039;Apache-HttpClient/4.2.2 (java 1.5)&#039;,&lt;br /&gt;
    &#039;host&#039;: &#039;xxxxxxxxxxxxxxxx&#039;,&lt;br /&gt;
    &#039;path&#039;: &#039;/index.php/admin/remotecontrol&#039;,&lt;br /&gt;
    &#039;connection&#039;: &#039;keep-alive&#039;,&lt;br /&gt;
    &#039;content-type&#039;: &#039;application/json&#039;&lt;br /&gt;
  }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
//*******AUTHENTIFICATION*******&lt;br /&gt;
options.body = JSON.stringify({method:&#039;get_session_key&#039;,params:[&#039;myusername&#039;,&#039;mypassword&#039;],id:1});&lt;br /&gt;
&lt;br /&gt;
request(options, function(error, response, body){&lt;br /&gt;
  if (!error &amp;amp;&amp;amp; response.statusCode == 200) {&lt;br /&gt;
      body = JSON.parse(body);&lt;br /&gt;
&lt;br /&gt;
    //*********KEEP THE KEY*********  &lt;br /&gt;
    if(SESSIONKEY===&amp;quot;&amp;quot;) {&lt;br /&gt;
      console.log(&amp;quot;NEW KEY --&amp;gt;&amp;quot;+body.result);&lt;br /&gt;
      SESSIONKEY=body.result;&lt;br /&gt;
      nextFonction();&lt;br /&gt;
    } &lt;br /&gt;
  }&lt;br /&gt;
  else console.log(&amp;quot;ERROR --&amp;gt;&amp;quot;+body);  &lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== R example and helper ==&lt;br /&gt;
&lt;br /&gt;
The easiest way to use lsrc2 is by means of the limer package, See https://github.com/cloudyr/limer&lt;br /&gt;
&lt;br /&gt;
Example of usage of this client&lt;br /&gt;
&amp;lt;source lang=R&amp;gt;&lt;br /&gt;
# first limer (check version: must be recent) must be installed&lt;br /&gt;
if(!require(&amp;quot;devtools&amp;quot;)) {&lt;br /&gt;
  install.packages(&amp;quot;devtools&amp;quot;)&lt;br /&gt;
  library(&amp;quot;devtools&amp;quot;)&lt;br /&gt;
}&lt;br /&gt;
install_github(&amp;quot;cloudyr/limer&amp;quot;)&lt;br /&gt;
#############################################################&lt;br /&gt;
&lt;br /&gt;
library(limer)&lt;br /&gt;
&lt;br /&gt;
#change the next options (website, user, password)&lt;br /&gt;
options&lt;br /&gt;
(lime_api = &#039;https://www.XXX.nl/index.php/admin/remotecontrol&#039;)&lt;br /&gt;
options(lime_username = &#039;user&#039;)&lt;br /&gt;
options(lime_password = &#039;password&#039;)&lt;br /&gt;
#############################################################&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# first get a session access key&lt;br /&gt;
get_session_key()&lt;br /&gt;
&lt;br /&gt;
# list all surveys. A dataframe is returned&lt;br /&gt;
survey_df&amp;lt;-call_limer(method=&#039;list_surveys&#039;)&lt;br /&gt;
print(survey_df)&lt;br /&gt;
#    sid           surveyls_title startdate             expires active&lt;br /&gt;
#1  999999  XXXX               NA 2016-03-08 15:20:30      Y&lt;br /&gt;
#2  999998  XXXX               NA   &amp;lt;NA&amp;gt;      Y&lt;br /&gt;
&lt;br /&gt;
#Read the data of the first survey (sid=999999) into a data.frame. &lt;br /&gt;
#Notice that the default sLanguageCode = en, so maybe you have to &lt;br /&gt;
#specify another language (here: All languages)&lt;br /&gt;
data&amp;lt;- get_responses(iSurveyID= 999999, sLanguageCode= &#039;&#039;, sResponseType=&#039;short&#039;)&lt;br /&gt;
        &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= JSON-RPC notes =&lt;br /&gt;
&lt;br /&gt;
The content-type of the HTTP request must be application/json.  Most formatting errors or a failure to set the content-type header will result in a null response from the server (not a JSON response).  Below is an example of a valid request and response pair.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;Request:&lt;br /&gt;
&lt;br /&gt;
 HTTP headers:&lt;br /&gt;
&lt;br /&gt;
   content-type=application/json&lt;br /&gt;
&lt;br /&gt;
   connection=Keep-Alive&lt;br /&gt;
&lt;br /&gt;
   host=mylimesurveyhost.com&lt;br /&gt;
&lt;br /&gt;
   content-length=67&lt;br /&gt;
&lt;br /&gt;
   user-agent=Apache-HttpClient/4.2.2 (java 1.5)&lt;br /&gt;
&lt;br /&gt;
 Post body:&lt;br /&gt;
&lt;br /&gt;
   {&amp;quot;method&amp;quot;:&amp;quot;get_session_key&amp;quot;,&amp;quot;params&amp;quot;:[&amp;quot;admin&amp;quot;,&amp;quot;mypassword&amp;quot;],&amp;quot;id&amp;quot;:1}&lt;br /&gt;
&lt;br /&gt;
Response body:&lt;br /&gt;
&lt;br /&gt;
 {&amp;quot;id&amp;quot;:1,&amp;quot;result&amp;quot;:&amp;quot;6htqat38fyr4v7iu72nqgv7xgavkvfcz&amp;quot;,&amp;quot;error&amp;quot;:null}&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>LimeAJ</name></author>
	</entry>
	<entry>
		<id>https://www.limesurvey.org/manual/index.php?title=Authentication_plugins&amp;diff=76230</id>
		<title>Authentication plugins</title>
		<link rel="alternate" type="text/html" href="https://www.limesurvey.org/manual/index.php?title=Authentication_plugins&amp;diff=76230"/>
		<updated>2017-08-14T18:33:15Z</updated>

		<summary type="html">&lt;p&gt;LimeAJ: /* LDAP */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This is an overview of the authentication plugins currently shipped with LimeSurvey. If you want to extend or develop your own authentication plugin, please see [[Authentication_plugin development]]&lt;br /&gt;
&lt;br /&gt;
== Internal database ==&lt;br /&gt;
This plugin is the default and can not be disabled. It uses the built in LimeSurvey database. It is a fall-back mechanism so that you can always login to the installation when needed.&lt;br /&gt;
&lt;br /&gt;
== LDAP ==&lt;br /&gt;
By activating this plugin you can perform basic authentication against an LDAP server. Make sure your PHP configuration has LDAP support enabled.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Enabling and configuring settings for plugin AuthLDAP v2.05+&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Enable LDAP in PHP.INI.&lt;br /&gt;
Verify that [http://php.net/manual/en/function.phpinfo.php phpinfo.php] shows that LDAP is enabled.&lt;br /&gt;
The location of LimeSurvey&#039;s built-in phpinfo.php is: Upper Right Menu -- Configuration -- Settings -- Global Settings.  Then, below the table, you will have a link for &amp;quot;Show PHPInfo&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Go to LimeSurvey Plugin Manager.&lt;br /&gt;
&lt;br /&gt;
Configure LDAP plugin.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Simple Example settings ===&lt;br /&gt;
Ldap server e.g. ldap://ldap.mydomain.com: ldap://ldap.mydomain.com&lt;br /&gt;
Port number (default when omitted is 389):&lt;br /&gt;
LDAP version (LDAPv2 = 2), e.g. 3: 3&lt;br /&gt;
Username prefix cn= or uid=: cn=&lt;br /&gt;
Username suffix e.g. @mydomain.com or remaining part of ldap query: ,OU=people,DC=mydomain,DC=com&lt;br /&gt;
Create a LimeSurvey administrator with the same name as a AD(active directory) user account.&lt;br /&gt;
Log in using the AD credentials(username and password).&lt;br /&gt;
&lt;br /&gt;
=== Example settings AD2008 &amp;amp; 2.05+ ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Settings working with Active Directory 2008 and 2.05+ (build 140520) with AuthLDAP plugin &#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==== Authentication with LDAP and &#039;&#039;userPrincipalName&#039;&#039; attribute ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: Authentication with &#039;&#039;userPrincipalName&#039;&#039; attribute (ie: firstname.lastname@example.intra). Create a LimeSurvey user with the same name as a AD(active directory) user account :&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Username&#039;&#039;: &#039;&#039;&#039;firstname.lastname@example.intra&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Email&#039;&#039;: &#039;&#039;&#039;firstname.lastname@example.intra&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Full name&#039;&#039;: &#039;&#039;&#039;Firstname LASTNAME&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Then configure the plugin : &#039;&#039;Plugin Manager &amp;gt; LDAP &amp;gt; Configure&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Ldap server e.g. ldap://ldap.example.intra&#039;&#039;: &#039;&#039;&#039;ldap://ldap.example.intra&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Port number (default when omitted is 389)&#039;&#039;: &#039;&#039;&#039;389&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;LDAP version (LDAPv2 = 2), e.g. 3&#039;&#039;: &#039;&#039;&#039;LDAPv3&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Username prefix cn= or uid=: cn=&#039;&#039;: &#039;&#039;&#039;empty&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Username suffix e.g. @example.intra or remaining part of ldap query&#039;&#039;: &#039;&#039;&#039;empty&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Log in using the AD credentials (username: &#039;&#039;&#039;firstname.lastname@example.intra&#039;&#039;&#039; and password).&lt;br /&gt;
&lt;br /&gt;
==== Authentication with LDAP and &#039;&#039;sAMaccountName&#039;&#039; attribute ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: Authentication with &#039;&#039;sAMaccountName&#039;&#039; attribute (ie: firstname.lastname). Create a LimeSurvey user with the same name as a AD(active directory) user account :&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Username&#039;&#039;: &#039;&#039;&#039;firstname.lastname&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Email&#039;&#039;: &#039;&#039;&#039;firstname.lastname@example.intra&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Full name&#039;&#039;: &#039;&#039;&#039;Firstname LASTNAME&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Then configure the plugin : &#039;&#039;Plugin Manager &amp;gt; LDAP &amp;gt; Configure&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Ldap server e.g. ldap://ldap.example.com&#039;&#039;: &#039;&#039;&#039;ldap://ldap.example.intra&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Port number (default when omitted is 389)&#039;&#039;: &#039;&#039;&#039;389&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;LDAP version (LDAPv2 = 2), e.g. 3&#039;&#039;: &#039;&#039;&#039;LDAPv3&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Username prefix cn= or uid=: cn=&#039;&#039;: &#039;&#039;&#039;empty&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Username suffix e.g. @example.com or remaining part of ldap query&#039;&#039;: &#039;&#039;&#039;@example.intra&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Log in using the AD credentials (username: &#039;&#039;&#039;firstname.lastname&#039;&#039;&#039; and password).&lt;br /&gt;
&lt;br /&gt;
==== Authentication with LDAPS and &#039;&#039;sAMaccountName&#039;&#039; attribute ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: Authentication with &#039;&#039;sAMaccountName&#039;&#039; attribute (ie: firstname.lastname). Create a LimeSurvey user with the same name as a AD(active directory) user account :&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Username&#039;&#039;: &#039;&#039;&#039;firstname.lastname&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Email&#039;&#039;: &#039;&#039;&#039;firstname.lastname@example.intra&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Full name&#039;&#039;: &#039;&#039;&#039;Firstname LASTNAME&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Then configure the plugin : &#039;&#039;Plugin Manager &amp;gt; LDAP &amp;gt; Configure&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Ldap server e.g. ldap://ldap.example.com&#039;&#039;: &#039;&#039;&#039;ldaps://ldap.example.intra&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Port number (default when omitted is 389)&#039;&#039;: &#039;&#039;&#039;636&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;LDAP version (LDAPv2 = 2), e.g. 3&#039;&#039;: &#039;&#039;&#039;LDAPv3&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Username prefix cn= or uid=: cn=&#039;&#039;: &#039;&#039;&#039;empty&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Username suffix e.g. @example.intra or remaining part of ldap query&#039;&#039;: &#039;&#039;&#039;@example.intra&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Log in using the AD credentials (username: &#039;&#039;&#039;firstname.lastname&#039;&#039;&#039; and password).&lt;br /&gt;
&lt;br /&gt;
=== Example settings OpenLDAP &amp;amp; 2.05+ ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Settings working with OpenLDAP and 2.05+ (git version Feb. 2015) with AuthLDAP plugin &#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==== Authentication with LDAP and &#039;&#039;uid&#039;&#039; attribute ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: Authentication with &#039;&#039;uid&#039;&#039; attribute. Create a LimeSurvey user with the same name as a the LDAP user account.&lt;br /&gt;
&lt;br /&gt;
Then configure the plugin : &#039;&#039;Plugin Manager &amp;gt; LDAP &amp;gt; Configure&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Ldap server e.g. ldap://ldap.mydomain.com&#039;&#039;: &#039;&#039;&#039;ldap://ldap.mydomain.com&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;Port number (default when omitted is 389)&#039;&#039;: &#039;&#039;&#039;(389 or leave blank)&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;LDAP version (LDAPv2 = 2), e.g. 3&#039;&#039;: &#039;&#039;&#039;LDAPv3&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;Select true if referrals must be followed (use false for ActiveDirectory)&#039;&#039;: &#039;&#039;&#039;(leave blank)&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;Check to enable Start-TLS encryption When using LDAPv3&#039;&#039;: &#039;&#039;&#039;False&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;Select how to perform authentication&#039;&#039;: &#039;&#039;&#039;Search and bind&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;Attribute to compare to the given login can be uid, cn, mail, ...&#039;&#039;: &#039;&#039;&#039;uid&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;Base DN for the user search operation&#039;&#039;: &#039;&#039;&#039;ou=people,dc=mydomain,dc=com&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;Optional extra LDAP filter to be ANDed to the basic (searchuserattribute=username) filter. Don&#039;t forget the outmost enclosing parentheses&#039;&#039;: &#039;&#039;&#039;(leave blank)&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;Optional DN of the LDAP account used to search for the end-user&#039;s DN. An anonymous bind is performed if empty.&#039;&#039;: &#039;&#039;&#039;cn=admin,dc=mydomain,dc=com&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;Password of the LDAP account used to search for the end-user&#039;s DN if previoulsy set.&#039;&#039;: &#039;&#039;&#039;password&#039;&#039;&#039; (appears!)&lt;br /&gt;
* &#039;&#039;Check to make default authentication method&#039;&#039;: &#039;&#039;&#039;(as you wish)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Log in using the LDAP credentials (username: &#039;&#039;&#039;user&#039;&#039;&#039; and password).&lt;br /&gt;
&lt;br /&gt;
==== Authentication with OpenLDAP, &#039;&#039;uid&#039;&#039; attribute, and group restriction [2.62+] ====&lt;br /&gt;
&lt;br /&gt;
Some applications require a separate LDAP query (beyond the user search and bind to check password) to determine if the user has sufficient authorization. For example, let&#039;s assume that LDAP has a &amp;lt;code&amp;gt;Groups&amp;lt;/code&amp;gt; OU that includes an entry identified by &amp;lt;code&amp;gt;cn=limeusers&amp;lt;/code&amp;gt; and our policy is that for a user to be authorized to use LimeSurvey that entry must include an attribute of the form &amp;lt;code&amp;gt;memberUid=&amp;lt;i&amp;gt;username&amp;lt;/i&amp;gt;&amp;lt;/code&amp;gt; where &#039;&#039;username&#039;&#039; is the username (uid) entered by the user attempting to login. To configure LDAP for that, set up basic &#039;&#039;uid&#039;&#039; authentication as above and then set the following additional (optional) parameters:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Optional base DN for group restriction&#039;&#039;: &amp;lt;code&amp;gt;ou=Groups,dc=mydomain,dc=com&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;Optional filter for group restriction&#039;&#039;: &amp;lt;code&amp;gt;(&amp;amp;(cn=limeusers)(memberUid=$username))&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note:&lt;br /&gt;
# &amp;lt;code&amp;gt;$username&amp;lt;/code&amp;gt; is a magic value (in the context of the filter parameter) that is replaced by the username entered by the user when logging in.&lt;br /&gt;
# Although intended for testing group membership as above, this optional &amp;quot;group restriction&amp;quot; capability can be used to add any authorization check that can be expressed as a separate filtered search like this.&lt;br /&gt;
# Before specifying a group restriction this way, verify that basic LDAP authentication is working correctly.&lt;br /&gt;
# If either of the group restriction parameters is empty then the group restriction step will not be applied.&lt;br /&gt;
&lt;br /&gt;
== Webserver authentication ==&lt;br /&gt;
&lt;br /&gt;
This plugin leaves authentication to the webserver and reads the result from a configurable server setting. This method has been around for a while, and was configured from config.php. If you used this authentication, you should enable the plugin in the plugins menu and move your configuration from config.php to the plugin&#039;s settings. Feel free to contact the team via the bugtracker or irc-channel if it no longer functions the way it did before.&lt;br /&gt;
&lt;br /&gt;
[[Category:Plugins]]&lt;/div&gt;</summary>
		<author><name>LimeAJ</name></author>
	</entry>
	<entry>
		<id>https://www.limesurvey.org/manual/index.php?title=Authentication_plugins&amp;diff=76229</id>
		<title>Authentication plugins</title>
		<link rel="alternate" type="text/html" href="https://www.limesurvey.org/manual/index.php?title=Authentication_plugins&amp;diff=76229"/>
		<updated>2017-08-14T18:33:05Z</updated>

		<summary type="html">&lt;p&gt;LimeAJ: /* LDAP */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This is an overview of the authentication plugins currently shipped with LimeSurvey. If you want to extend or develop your own authentication plugin, please see [[Authentication_plugin development]]&lt;br /&gt;
&lt;br /&gt;
== Internal database ==&lt;br /&gt;
This plugin is the default and can not be disabled. It uses the built in LimeSurvey database. It is a fall-back mechanism so that you can always login to the installation when needed.&lt;br /&gt;
&lt;br /&gt;
== LDAP ==&lt;br /&gt;
By activating this plugin you can perform basic authentication against an LDAP server. Make sure your PHP configuration has LDAP support enabled.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Enabling and configuring settings for plugin AuthLDAP v2.05+&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Enable LDAP in PHP.INI.&lt;br /&gt;
Verify that [http://php.net/manual/en/function.phpinfo.php phpinfo.php] shows that LDAP is enabled.&lt;br /&gt;
The location of LimeSurvey&#039;s built-in phpinfo.php is: Upper Right Menu -- Configuration -- Settings -- Global Settings.  Then, below the table, you will have a link for &amp;quot;Show PHPInfo.&lt;br /&gt;
&lt;br /&gt;
Go to LimeSurvey Plugin Manager.&lt;br /&gt;
&lt;br /&gt;
Configure LDAP plugin.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Simple Example settings ===&lt;br /&gt;
Ldap server e.g. ldap://ldap.mydomain.com: ldap://ldap.mydomain.com&lt;br /&gt;
Port number (default when omitted is 389):&lt;br /&gt;
LDAP version (LDAPv2 = 2), e.g. 3: 3&lt;br /&gt;
Username prefix cn= or uid=: cn=&lt;br /&gt;
Username suffix e.g. @mydomain.com or remaining part of ldap query: ,OU=people,DC=mydomain,DC=com&lt;br /&gt;
Create a LimeSurvey administrator with the same name as a AD(active directory) user account.&lt;br /&gt;
Log in using the AD credentials(username and password).&lt;br /&gt;
&lt;br /&gt;
=== Example settings AD2008 &amp;amp; 2.05+ ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Settings working with Active Directory 2008 and 2.05+ (build 140520) with AuthLDAP plugin &#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==== Authentication with LDAP and &#039;&#039;userPrincipalName&#039;&#039; attribute ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: Authentication with &#039;&#039;userPrincipalName&#039;&#039; attribute (ie: firstname.lastname@example.intra). Create a LimeSurvey user with the same name as a AD(active directory) user account :&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Username&#039;&#039;: &#039;&#039;&#039;firstname.lastname@example.intra&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Email&#039;&#039;: &#039;&#039;&#039;firstname.lastname@example.intra&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Full name&#039;&#039;: &#039;&#039;&#039;Firstname LASTNAME&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Then configure the plugin : &#039;&#039;Plugin Manager &amp;gt; LDAP &amp;gt; Configure&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Ldap server e.g. ldap://ldap.example.intra&#039;&#039;: &#039;&#039;&#039;ldap://ldap.example.intra&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Port number (default when omitted is 389)&#039;&#039;: &#039;&#039;&#039;389&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;LDAP version (LDAPv2 = 2), e.g. 3&#039;&#039;: &#039;&#039;&#039;LDAPv3&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Username prefix cn= or uid=: cn=&#039;&#039;: &#039;&#039;&#039;empty&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Username suffix e.g. @example.intra or remaining part of ldap query&#039;&#039;: &#039;&#039;&#039;empty&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Log in using the AD credentials (username: &#039;&#039;&#039;firstname.lastname@example.intra&#039;&#039;&#039; and password).&lt;br /&gt;
&lt;br /&gt;
==== Authentication with LDAP and &#039;&#039;sAMaccountName&#039;&#039; attribute ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: Authentication with &#039;&#039;sAMaccountName&#039;&#039; attribute (ie: firstname.lastname). Create a LimeSurvey user with the same name as a AD(active directory) user account :&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Username&#039;&#039;: &#039;&#039;&#039;firstname.lastname&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Email&#039;&#039;: &#039;&#039;&#039;firstname.lastname@example.intra&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Full name&#039;&#039;: &#039;&#039;&#039;Firstname LASTNAME&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Then configure the plugin : &#039;&#039;Plugin Manager &amp;gt; LDAP &amp;gt; Configure&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Ldap server e.g. ldap://ldap.example.com&#039;&#039;: &#039;&#039;&#039;ldap://ldap.example.intra&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Port number (default when omitted is 389)&#039;&#039;: &#039;&#039;&#039;389&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;LDAP version (LDAPv2 = 2), e.g. 3&#039;&#039;: &#039;&#039;&#039;LDAPv3&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Username prefix cn= or uid=: cn=&#039;&#039;: &#039;&#039;&#039;empty&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Username suffix e.g. @example.com or remaining part of ldap query&#039;&#039;: &#039;&#039;&#039;@example.intra&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Log in using the AD credentials (username: &#039;&#039;&#039;firstname.lastname&#039;&#039;&#039; and password).&lt;br /&gt;
&lt;br /&gt;
==== Authentication with LDAPS and &#039;&#039;sAMaccountName&#039;&#039; attribute ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: Authentication with &#039;&#039;sAMaccountName&#039;&#039; attribute (ie: firstname.lastname). Create a LimeSurvey user with the same name as a AD(active directory) user account :&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Username&#039;&#039;: &#039;&#039;&#039;firstname.lastname&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Email&#039;&#039;: &#039;&#039;&#039;firstname.lastname@example.intra&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Full name&#039;&#039;: &#039;&#039;&#039;Firstname LASTNAME&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Then configure the plugin : &#039;&#039;Plugin Manager &amp;gt; LDAP &amp;gt; Configure&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Ldap server e.g. ldap://ldap.example.com&#039;&#039;: &#039;&#039;&#039;ldaps://ldap.example.intra&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Port number (default when omitted is 389)&#039;&#039;: &#039;&#039;&#039;636&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;LDAP version (LDAPv2 = 2), e.g. 3&#039;&#039;: &#039;&#039;&#039;LDAPv3&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Username prefix cn= or uid=: cn=&#039;&#039;: &#039;&#039;&#039;empty&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Username suffix e.g. @example.intra or remaining part of ldap query&#039;&#039;: &#039;&#039;&#039;@example.intra&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Log in using the AD credentials (username: &#039;&#039;&#039;firstname.lastname&#039;&#039;&#039; and password).&lt;br /&gt;
&lt;br /&gt;
=== Example settings OpenLDAP &amp;amp; 2.05+ ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Settings working with OpenLDAP and 2.05+ (git version Feb. 2015) with AuthLDAP plugin &#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==== Authentication with LDAP and &#039;&#039;uid&#039;&#039; attribute ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: Authentication with &#039;&#039;uid&#039;&#039; attribute. Create a LimeSurvey user with the same name as a the LDAP user account.&lt;br /&gt;
&lt;br /&gt;
Then configure the plugin : &#039;&#039;Plugin Manager &amp;gt; LDAP &amp;gt; Configure&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Ldap server e.g. ldap://ldap.mydomain.com&#039;&#039;: &#039;&#039;&#039;ldap://ldap.mydomain.com&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;Port number (default when omitted is 389)&#039;&#039;: &#039;&#039;&#039;(389 or leave blank)&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;LDAP version (LDAPv2 = 2), e.g. 3&#039;&#039;: &#039;&#039;&#039;LDAPv3&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;Select true if referrals must be followed (use false for ActiveDirectory)&#039;&#039;: &#039;&#039;&#039;(leave blank)&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;Check to enable Start-TLS encryption When using LDAPv3&#039;&#039;: &#039;&#039;&#039;False&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;Select how to perform authentication&#039;&#039;: &#039;&#039;&#039;Search and bind&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;Attribute to compare to the given login can be uid, cn, mail, ...&#039;&#039;: &#039;&#039;&#039;uid&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;Base DN for the user search operation&#039;&#039;: &#039;&#039;&#039;ou=people,dc=mydomain,dc=com&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;Optional extra LDAP filter to be ANDed to the basic (searchuserattribute=username) filter. Don&#039;t forget the outmost enclosing parentheses&#039;&#039;: &#039;&#039;&#039;(leave blank)&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;Optional DN of the LDAP account used to search for the end-user&#039;s DN. An anonymous bind is performed if empty.&#039;&#039;: &#039;&#039;&#039;cn=admin,dc=mydomain,dc=com&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;Password of the LDAP account used to search for the end-user&#039;s DN if previoulsy set.&#039;&#039;: &#039;&#039;&#039;password&#039;&#039;&#039; (appears!)&lt;br /&gt;
* &#039;&#039;Check to make default authentication method&#039;&#039;: &#039;&#039;&#039;(as you wish)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Log in using the LDAP credentials (username: &#039;&#039;&#039;user&#039;&#039;&#039; and password).&lt;br /&gt;
&lt;br /&gt;
==== Authentication with OpenLDAP, &#039;&#039;uid&#039;&#039; attribute, and group restriction [2.62+] ====&lt;br /&gt;
&lt;br /&gt;
Some applications require a separate LDAP query (beyond the user search and bind to check password) to determine if the user has sufficient authorization. For example, let&#039;s assume that LDAP has a &amp;lt;code&amp;gt;Groups&amp;lt;/code&amp;gt; OU that includes an entry identified by &amp;lt;code&amp;gt;cn=limeusers&amp;lt;/code&amp;gt; and our policy is that for a user to be authorized to use LimeSurvey that entry must include an attribute of the form &amp;lt;code&amp;gt;memberUid=&amp;lt;i&amp;gt;username&amp;lt;/i&amp;gt;&amp;lt;/code&amp;gt; where &#039;&#039;username&#039;&#039; is the username (uid) entered by the user attempting to login. To configure LDAP for that, set up basic &#039;&#039;uid&#039;&#039; authentication as above and then set the following additional (optional) parameters:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Optional base DN for group restriction&#039;&#039;: &amp;lt;code&amp;gt;ou=Groups,dc=mydomain,dc=com&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;Optional filter for group restriction&#039;&#039;: &amp;lt;code&amp;gt;(&amp;amp;(cn=limeusers)(memberUid=$username))&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note:&lt;br /&gt;
# &amp;lt;code&amp;gt;$username&amp;lt;/code&amp;gt; is a magic value (in the context of the filter parameter) that is replaced by the username entered by the user when logging in.&lt;br /&gt;
# Although intended for testing group membership as above, this optional &amp;quot;group restriction&amp;quot; capability can be used to add any authorization check that can be expressed as a separate filtered search like this.&lt;br /&gt;
# Before specifying a group restriction this way, verify that basic LDAP authentication is working correctly.&lt;br /&gt;
# If either of the group restriction parameters is empty then the group restriction step will not be applied.&lt;br /&gt;
&lt;br /&gt;
== Webserver authentication ==&lt;br /&gt;
&lt;br /&gt;
This plugin leaves authentication to the webserver and reads the result from a configurable server setting. This method has been around for a while, and was configured from config.php. If you used this authentication, you should enable the plugin in the plugins menu and move your configuration from config.php to the plugin&#039;s settings. Feel free to contact the team via the bugtracker or irc-channel if it no longer functions the way it did before.&lt;br /&gt;
&lt;br /&gt;
[[Category:Plugins]]&lt;/div&gt;</summary>
		<author><name>LimeAJ</name></author>
	</entry>
	<entry>
		<id>https://www.limesurvey.org/manual/index.php?title=LimeSurvey_Manual&amp;diff=76228</id>
		<title>LimeSurvey Manual</title>
		<link rel="alternate" type="text/html" href="https://www.limesurvey.org/manual/index.php?title=LimeSurvey_Manual&amp;diff=76228"/>
		<updated>2017-08-14T17:33:35Z</updated>

		<summary type="html">&lt;p&gt;LimeAJ: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;languages /&amp;gt;&lt;br /&gt;
&amp;lt;translate&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot; style= &amp;quot;margin-top:1em;background-color:#eeffee;-webkit-box-shadow: 0 10px 6px -6px #777;-moz-box-shadow: 0 10px 6px -6px #777;box-shadow: 0 10px 6px -6px #777;&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;span style=&#039;font-size:188%&#039;&amp;gt;&#039;&#039;&#039;Help us to update this manual!&#039;&#039;&#039;&amp;lt;/span&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;span style=&#039;&#039;&amp;gt; This manual is a Wiki - just log in with your LimeSurvey.org account and start editing!&amp;lt;/span&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
=General= &amp;lt;!--T:10--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:1--&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;clear:right;float:right;&amp;quot;&amp;gt;&amp;lt;div class=&amp;quot;simplebox&amp;quot;&amp;gt;&lt;br /&gt;
Main Chapters:&lt;br /&gt;
*[[Installation]]&lt;br /&gt;
*[[Administering LimeSurvey]]&lt;br /&gt;
*[[Getting started]]&lt;br /&gt;
*[[Creating surveys - introduction]]&lt;br /&gt;
*[[Managing surveys]]&lt;br /&gt;
*[[Not categorized and advanced features]]&lt;br /&gt;
*[[General FAQ]]&lt;br /&gt;
*[[LimeSurvey glossary]]&lt;br /&gt;
*[[How to design a good survey (guide)]]&lt;br /&gt;
*[[Workarounds]]&lt;br /&gt;
*[[License]]&lt;br /&gt;
*[[Version change log]]&lt;br /&gt;
*[[Plugins]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&amp;lt;/div&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:2--&amp;gt;&lt;br /&gt;
[https://www.limesurvey.com/ LimeSurvey] allows users to quickly create intuitive, powerful, online question-and-answer surveys that can work for tens to thousands of participants without much effort. The survey software itself is self-guiding for the respondents who are participating. This manual is thus focused at how to install the application, administer the installation, and support survey creators, administrators and report generation users alike.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:4--&amp;gt;&lt;br /&gt;
There has been a big ramp-up in development the last few years leading to many new features and changes. Make sure to upgrade to the [https://www.limesurvey.org/about-limesurvey/download latest version] to make use of the capabilities highlighted here.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:5--&amp;gt;&lt;br /&gt;
Look to the far right for the main chapters of the manual. Otherwise, scroll down further to see the complete table of contents here and go directly to the topic you are interested in.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:6--&amp;gt;&lt;br /&gt;
Still having trouble finding what you want? Don&#039;t forget the general &#039;&#039;&#039;search box&#039;&#039;&#039;, our [[General FAQ]] and [[Workarounds]] list, look in our [https://www.limesurvey.org/en/forum/ discussion forums], and check the irc #limesurvey in freenode.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:7--&amp;gt;&lt;br /&gt;
Remember that [https://www.limesurvey.org/ LimeSurvey] is an open-source, free software application. See something missing or incorrect? Then help us fix it. This documentation is a Wiki that can be edited by you or anyone else. Or [https://donate.limesurvey.org donate] to help support the core development group trying to make a difference.&lt;br /&gt;
&lt;br /&gt;
= Manual - Table of contents= &amp;lt;!--T:8--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:9--&amp;gt;&lt;br /&gt;
*[[Installation]]&lt;br /&gt;
**[[Optional settings]]&lt;br /&gt;
**[[Upgrading from a previous version]]&lt;br /&gt;
***[[ComfortUpdate]]&lt;br /&gt;
**[[Installation using a command line interface (CLI)]]&lt;br /&gt;
**[[Transferring an installation]]&lt;br /&gt;
**[[Installation FAQ]]&lt;br /&gt;
***[[Installation security hints]]&lt;br /&gt;
*[[Getting started]]&lt;br /&gt;
**[[First login - your user preferences]]&lt;br /&gt;
*[[Administering LimeSurvey]]&lt;br /&gt;
**[[Global settings]]&lt;br /&gt;
**[[Manage users]]&lt;br /&gt;
**[[Manage user groups]]&lt;br /&gt;
**[[Label sets]]&lt;br /&gt;
**[[The template editor]]&lt;br /&gt;
**[[Localisation]]&lt;br /&gt;
**[[Survey status screen]]&lt;br /&gt;
**[[Central participants database]]&lt;br /&gt;
*[[Creating surveys - introduction]]&lt;br /&gt;
**[[Survey settings]]&lt;br /&gt;
***[[Importing a survey structure]]&lt;br /&gt;
***[[Survey security settings]]&lt;br /&gt;
**[[Creating a question group]]&lt;br /&gt;
***[[Change group order]]&lt;br /&gt;
**[[Adding a question]]&lt;br /&gt;
***[[Question types]]&lt;br /&gt;
****[[Question type - Array]]&lt;br /&gt;
****[[Question type - Array by column]]&lt;br /&gt;
****[[Question type - Array dual scale]]&lt;br /&gt;
****[[Question type - Array (5 point choice)]]&lt;br /&gt;
****[[Question type - Array (10 point choice)]]&lt;br /&gt;
****[[Question type - Array (Increase-Same-Decrease)]]&lt;br /&gt;
****[[Question type - Array (Numbers)]]&lt;br /&gt;
****[[Question type - Array (Texts)]]&lt;br /&gt;
****[[Question type - Array (Yes-No-Uncertain)]]&lt;br /&gt;
****[[Question type - Date]]&lt;br /&gt;
****[[Question type - Equation]]&lt;br /&gt;
****[[Question type - File upload]]&lt;br /&gt;
****[[Question type - Gender]]&lt;br /&gt;
****[[Question type - Language switch]]&lt;br /&gt;
****[[Question type - Numerical input]]&lt;br /&gt;
****[[Question type - Multiple numerical input]]&lt;br /&gt;
****[[Question type - Ranking]]&lt;br /&gt;
****[[Question type - Text display]]&lt;br /&gt;
****[[Question type - Yes-No]]&lt;br /&gt;
****[[Question type - Multiple choice]]&lt;br /&gt;
****[[Question type - Multiple choice with comments]]&lt;br /&gt;
****[[Question type - 5 point choice]]&lt;br /&gt;
****[[Question type - List (Dropdown)]]&lt;br /&gt;
****[[Question type - List (Radio)]]&lt;br /&gt;
****[[Question type - List with comment]]&lt;br /&gt;
****[[Question type - Short free text]]&lt;br /&gt;
****[[Question type - Long free text]]&lt;br /&gt;
****[[Question type - Huge free text]]&lt;br /&gt;
****[[Question type - Multiple short text]]&lt;br /&gt;
***[[Change question order]]&lt;br /&gt;
***[[Question preview]]&lt;br /&gt;
***[[Adding answers or subquestions]]&lt;br /&gt;
**[[Setting conditions]]&lt;br /&gt;
***[[Expression Manager]]&lt;br /&gt;
****[[Expression Manager for developers]]&lt;br /&gt;
****[[Expression Manager how-tos]]&lt;br /&gt;
****[[Expression Manager roadmap]]&lt;br /&gt;
****[[Expression Manager examples]]&lt;br /&gt;
****[[Expression Manager sample surveys]]&lt;br /&gt;
***[[Show logic file]]&lt;br /&gt;
**[[Assessments]]&lt;br /&gt;
**[[Quotas]]&lt;br /&gt;
**[[Email templates]]&lt;br /&gt;
*[[Managing surveys]]&lt;br /&gt;
**[[Testing a survey]]&lt;br /&gt;
**[[Activating a survey]]&lt;br /&gt;
**[[Running a survey safely]]&lt;br /&gt;
**[[Browsing survey results]]&lt;br /&gt;
**[[Closing a survey]]&lt;br /&gt;
**[[Changing an active survey]]&lt;br /&gt;
**[[Survey participants]] (was: Tokens)&lt;br /&gt;
***[[Email bounce tracking system]]&lt;br /&gt;
**[[Iterate survey]]&lt;br /&gt;
**[[Data entry]]&lt;br /&gt;
**[[Statistics]]&lt;br /&gt;
**[[Exporting results]]&lt;br /&gt;
**[[Exporting a survey structure]]&lt;br /&gt;
***[[Tab Separated Value survey structure]]&lt;br /&gt;
**[[QueXML PDF Export]]&lt;br /&gt;
**[[Quick-translation]]&lt;br /&gt;
*[[Not categorized and advanced features]]&lt;br /&gt;
**[[SGQA identifier]]&lt;br /&gt;
**[[Using regular expressions]]&lt;br /&gt;
**[[URL fields]]&lt;br /&gt;
**[[RemoteControl 2 API]]&lt;br /&gt;
*[[General FAQ]]&lt;br /&gt;
*[[Troubleshooting]]&lt;br /&gt;
*[[LimeSurvey glossary]]&lt;br /&gt;
*[[How to design a good survey (guide)]]&lt;br /&gt;
*[[Workarounds]]&lt;br /&gt;
**[[Workarounds: Question design, layout and templating]]&lt;br /&gt;
**[[Workarounds: Manipulating a survey at runtime using Javascript]]&lt;br /&gt;
**[[Workarounds: Survey behaviour]]&lt;br /&gt;
**[[Workarounds: Further solutions provided by LimeSurvey users]]&lt;br /&gt;
*[[License]]&lt;br /&gt;
*[[Version change log]]&lt;br /&gt;
*[[Plugins]]&lt;br /&gt;
**[[Authentication plugins]]&lt;br /&gt;
**[[Available third party plugins]]&lt;br /&gt;
&lt;br /&gt;
=LimeSurvey development= &amp;lt;!--T:14--&amp;gt;&lt;br /&gt;
*[[Development overview]] - General pages about LimeSurvey development&lt;br /&gt;
*[[LimeSurvey 2.x development documentation]]&lt;br /&gt;
&lt;br /&gt;
=Translating LimeSurvey= &amp;lt;!--T:15--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:16--&amp;gt;&lt;br /&gt;
If you want to &#039;&#039;&#039;add new translations&#039;&#039;&#039; or &#039;&#039;&#039;correct a translation&#039;&#039;&#039; please follow these instructions:&lt;br /&gt;
*[[Translating LimeSurvey|How to translate LimeSurvey]]&lt;br /&gt;
&lt;br /&gt;
=Semester of Code participation= &amp;lt;!--T:18--&amp;gt;&lt;br /&gt;
*[[Semester of Code 2014]]&lt;br /&gt;
&lt;br /&gt;
=Google Summer of Code / Code-In participation= &amp;lt;!--T:17--&amp;gt;&lt;br /&gt;
*[[Project ideas for GSoC 2015]]&lt;br /&gt;
*[[Project Ideas for GSoC 2013]]&lt;br /&gt;
*[[LimeSurvey Google Code-in 2012]]&lt;br /&gt;
*[[LimeSurvey Google Code-in 2011]]&lt;br /&gt;
*[[LimeSurvey GSoC 2011]]/[[GSoC getting started]]&lt;br /&gt;
*[[LimeSurvey GSoC 2010]]&lt;br /&gt;
*[[LimeSurvey GSoC 2009]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/translate&amp;gt;&lt;/div&gt;</summary>
		<author><name>LimeAJ</name></author>
	</entry>
	<entry>
		<id>https://www.limesurvey.org/manual/index.php?title=Authentication_plugins&amp;diff=76227</id>
		<title>Authentication plugins</title>
		<link rel="alternate" type="text/html" href="https://www.limesurvey.org/manual/index.php?title=Authentication_plugins&amp;diff=76227"/>
		<updated>2017-08-14T17:08:35Z</updated>

		<summary type="html">&lt;p&gt;LimeAJ: /* LDAP */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This is an overview of the authentication plugins currently shipped with LimeSurvey. If you want to extend or develop your own authentication plugin, please see [[Authentication_plugin development]]&lt;br /&gt;
&lt;br /&gt;
== Internal database ==&lt;br /&gt;
This plugin is the default and can not be disabled. It uses the built in LimeSurvey database. It is a fall-back mechanism so that you can always login to the installation when needed.&lt;br /&gt;
&lt;br /&gt;
== LDAP ==&lt;br /&gt;
By activating this plugin you can perform basic authentication against an LDAP server. Make sure your PHP configuration has LDAP support enabled.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Enabling and configuring settings for plugin AuthLDAP v2.05+&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Enable LDAP in PHP.INI.&lt;br /&gt;
Verify that [http://php.net/manual/en/function.phpinfo.php phpinfo.php] shows that LDAP is enabled.&lt;br /&gt;
&lt;br /&gt;
Go to LimeSurvey Plugin Manager.&lt;br /&gt;
&lt;br /&gt;
Configure LDAP plugin.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Simple Example settings ===&lt;br /&gt;
Ldap server e.g. ldap://ldap.mydomain.com: ldap://ldap.mydomain.com&lt;br /&gt;
Port number (default when omitted is 389):&lt;br /&gt;
LDAP version (LDAPv2 = 2), e.g. 3: 3&lt;br /&gt;
Username prefix cn= or uid=: cn=&lt;br /&gt;
Username suffix e.g. @mydomain.com or remaining part of ldap query: ,OU=people,DC=mydomain,DC=com&lt;br /&gt;
Create a LimeSurvey administrator with the same name as a AD(active directory) user account.&lt;br /&gt;
Log in using the AD credentials(username and password).&lt;br /&gt;
&lt;br /&gt;
=== Example settings AD2008 &amp;amp; 2.05+ ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Settings working with Active Directory 2008 and 2.05+ (build 140520) with AuthLDAP plugin &#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==== Authentication with LDAP and &#039;&#039;userPrincipalName&#039;&#039; attribute ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: Authentication with &#039;&#039;userPrincipalName&#039;&#039; attribute (ie: firstname.lastname@example.intra). Create a LimeSurvey user with the same name as a AD(active directory) user account :&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Username&#039;&#039;: &#039;&#039;&#039;firstname.lastname@example.intra&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Email&#039;&#039;: &#039;&#039;&#039;firstname.lastname@example.intra&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Full name&#039;&#039;: &#039;&#039;&#039;Firstname LASTNAME&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Then configure the plugin : &#039;&#039;Plugin Manager &amp;gt; LDAP &amp;gt; Configure&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Ldap server e.g. ldap://ldap.example.intra&#039;&#039;: &#039;&#039;&#039;ldap://ldap.example.intra&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Port number (default when omitted is 389)&#039;&#039;: &#039;&#039;&#039;389&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;LDAP version (LDAPv2 = 2), e.g. 3&#039;&#039;: &#039;&#039;&#039;LDAPv3&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Username prefix cn= or uid=: cn=&#039;&#039;: &#039;&#039;&#039;empty&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Username suffix e.g. @example.intra or remaining part of ldap query&#039;&#039;: &#039;&#039;&#039;empty&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Log in using the AD credentials (username: &#039;&#039;&#039;firstname.lastname@example.intra&#039;&#039;&#039; and password).&lt;br /&gt;
&lt;br /&gt;
==== Authentication with LDAP and &#039;&#039;sAMaccountName&#039;&#039; attribute ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: Authentication with &#039;&#039;sAMaccountName&#039;&#039; attribute (ie: firstname.lastname). Create a LimeSurvey user with the same name as a AD(active directory) user account :&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Username&#039;&#039;: &#039;&#039;&#039;firstname.lastname&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Email&#039;&#039;: &#039;&#039;&#039;firstname.lastname@example.intra&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Full name&#039;&#039;: &#039;&#039;&#039;Firstname LASTNAME&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Then configure the plugin : &#039;&#039;Plugin Manager &amp;gt; LDAP &amp;gt; Configure&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Ldap server e.g. ldap://ldap.example.com&#039;&#039;: &#039;&#039;&#039;ldap://ldap.example.intra&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Port number (default when omitted is 389)&#039;&#039;: &#039;&#039;&#039;389&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;LDAP version (LDAPv2 = 2), e.g. 3&#039;&#039;: &#039;&#039;&#039;LDAPv3&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Username prefix cn= or uid=: cn=&#039;&#039;: &#039;&#039;&#039;empty&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Username suffix e.g. @example.com or remaining part of ldap query&#039;&#039;: &#039;&#039;&#039;@example.intra&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Log in using the AD credentials (username: &#039;&#039;&#039;firstname.lastname&#039;&#039;&#039; and password).&lt;br /&gt;
&lt;br /&gt;
==== Authentication with LDAPS and &#039;&#039;sAMaccountName&#039;&#039; attribute ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: Authentication with &#039;&#039;sAMaccountName&#039;&#039; attribute (ie: firstname.lastname). Create a LimeSurvey user with the same name as a AD(active directory) user account :&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Username&#039;&#039;: &#039;&#039;&#039;firstname.lastname&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Email&#039;&#039;: &#039;&#039;&#039;firstname.lastname@example.intra&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Full name&#039;&#039;: &#039;&#039;&#039;Firstname LASTNAME&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Then configure the plugin : &#039;&#039;Plugin Manager &amp;gt; LDAP &amp;gt; Configure&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Ldap server e.g. ldap://ldap.example.com&#039;&#039;: &#039;&#039;&#039;ldaps://ldap.example.intra&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Port number (default when omitted is 389)&#039;&#039;: &#039;&#039;&#039;636&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;LDAP version (LDAPv2 = 2), e.g. 3&#039;&#039;: &#039;&#039;&#039;LDAPv3&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Username prefix cn= or uid=: cn=&#039;&#039;: &#039;&#039;&#039;empty&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Username suffix e.g. @example.intra or remaining part of ldap query&#039;&#039;: &#039;&#039;&#039;@example.intra&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Log in using the AD credentials (username: &#039;&#039;&#039;firstname.lastname&#039;&#039;&#039; and password).&lt;br /&gt;
&lt;br /&gt;
=== Example settings OpenLDAP &amp;amp; 2.05+ ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Settings working with OpenLDAP and 2.05+ (git version Feb. 2015) with AuthLDAP plugin &#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==== Authentication with LDAP and &#039;&#039;uid&#039;&#039; attribute ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: Authentication with &#039;&#039;uid&#039;&#039; attribute. Create a LimeSurvey user with the same name as a the LDAP user account.&lt;br /&gt;
&lt;br /&gt;
Then configure the plugin : &#039;&#039;Plugin Manager &amp;gt; LDAP &amp;gt; Configure&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Ldap server e.g. ldap://ldap.mydomain.com&#039;&#039;: &#039;&#039;&#039;ldap://ldap.mydomain.com&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;Port number (default when omitted is 389)&#039;&#039;: &#039;&#039;&#039;(389 or leave blank)&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;LDAP version (LDAPv2 = 2), e.g. 3&#039;&#039;: &#039;&#039;&#039;LDAPv3&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;Select true if referrals must be followed (use false for ActiveDirectory)&#039;&#039;: &#039;&#039;&#039;(leave blank)&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;Check to enable Start-TLS encryption When using LDAPv3&#039;&#039;: &#039;&#039;&#039;False&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;Select how to perform authentication&#039;&#039;: &#039;&#039;&#039;Search and bind&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;Attribute to compare to the given login can be uid, cn, mail, ...&#039;&#039;: &#039;&#039;&#039;uid&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;Base DN for the user search operation&#039;&#039;: &#039;&#039;&#039;ou=people,dc=mydomain,dc=com&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;Optional extra LDAP filter to be ANDed to the basic (searchuserattribute=username) filter. Don&#039;t forget the outmost enclosing parentheses&#039;&#039;: &#039;&#039;&#039;(leave blank)&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;Optional DN of the LDAP account used to search for the end-user&#039;s DN. An anonymous bind is performed if empty.&#039;&#039;: &#039;&#039;&#039;cn=admin,dc=mydomain,dc=com&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;Password of the LDAP account used to search for the end-user&#039;s DN if previoulsy set.&#039;&#039;: &#039;&#039;&#039;password&#039;&#039;&#039; (appears!)&lt;br /&gt;
* &#039;&#039;Check to make default authentication method&#039;&#039;: &#039;&#039;&#039;(as you wish)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Log in using the LDAP credentials (username: &#039;&#039;&#039;user&#039;&#039;&#039; and password).&lt;br /&gt;
&lt;br /&gt;
==== Authentication with OpenLDAP, &#039;&#039;uid&#039;&#039; attribute, and group restriction [2.62+] ====&lt;br /&gt;
&lt;br /&gt;
Some applications require a separate LDAP query (beyond the user search and bind to check password) to determine if the user has sufficient authorization. For example, let&#039;s assume that LDAP has a &amp;lt;code&amp;gt;Groups&amp;lt;/code&amp;gt; OU that includes an entry identified by &amp;lt;code&amp;gt;cn=limeusers&amp;lt;/code&amp;gt; and our policy is that for a user to be authorized to use LimeSurvey that entry must include an attribute of the form &amp;lt;code&amp;gt;memberUid=&amp;lt;i&amp;gt;username&amp;lt;/i&amp;gt;&amp;lt;/code&amp;gt; where &#039;&#039;username&#039;&#039; is the username (uid) entered by the user attempting to login. To configure LDAP for that, set up basic &#039;&#039;uid&#039;&#039; authentication as above and then set the following additional (optional) parameters:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Optional base DN for group restriction&#039;&#039;: &amp;lt;code&amp;gt;ou=Groups,dc=mydomain,dc=com&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;Optional filter for group restriction&#039;&#039;: &amp;lt;code&amp;gt;(&amp;amp;(cn=limeusers)(memberUid=$username))&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note:&lt;br /&gt;
# &amp;lt;code&amp;gt;$username&amp;lt;/code&amp;gt; is a magic value (in the context of the filter parameter) that is replaced by the username entered by the user when logging in.&lt;br /&gt;
# Although intended for testing group membership as above, this optional &amp;quot;group restriction&amp;quot; capability can be used to add any authorization check that can be expressed as a separate filtered search like this.&lt;br /&gt;
# Before specifying a group restriction this way, verify that basic LDAP authentication is working correctly.&lt;br /&gt;
# If either of the group restriction parameters is empty then the group restriction step will not be applied.&lt;br /&gt;
&lt;br /&gt;
== Webserver authentication ==&lt;br /&gt;
&lt;br /&gt;
This plugin leaves authentication to the webserver and reads the result from a configurable server setting. This method has been around for a while, and was configured from config.php. If you used this authentication, you should enable the plugin in the plugins menu and move your configuration from config.php to the plugin&#039;s settings. Feel free to contact the team via the bugtracker or irc-channel if it no longer functions the way it did before.&lt;br /&gt;
&lt;br /&gt;
[[Category:Plugins]]&lt;/div&gt;</summary>
		<author><name>LimeAJ</name></author>
	</entry>
	<entry>
		<id>https://www.limesurvey.org/manual/index.php?title=Authentication_plugins&amp;diff=76226</id>
		<title>Authentication plugins</title>
		<link rel="alternate" type="text/html" href="https://www.limesurvey.org/manual/index.php?title=Authentication_plugins&amp;diff=76226"/>
		<updated>2017-08-14T17:06:44Z</updated>

		<summary type="html">&lt;p&gt;LimeAJ: /* LDAP */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This is an overview of the authentication plugins currently shipped with LimeSurvey. If you want to extend or develop your own authentication plugin, please see [[Authentication_plugin development]]&lt;br /&gt;
&lt;br /&gt;
== Internal database ==&lt;br /&gt;
This plugin is the default and can not be disabled. It uses the built in LimeSurvey database. It is a fall-back mechanism so that you can always login to the installation when needed.&lt;br /&gt;
&lt;br /&gt;
== LDAP ==&lt;br /&gt;
By activating this plugin you can perform basic authentication against an LDAP server. Make sure your PHP configuration has LDAP support enabled.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Enabling and configuring settings for plugin AuthLDAP v2.05+&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Enable LDAP in PHP.INI.&lt;br /&gt;
Verify that [http://php.net/manual/en/function.phpinfo.php|phpinfo.php shows that LDAP is enabled].&lt;br /&gt;
&lt;br /&gt;
Go to LimeSurvey Plugin Manager.&lt;br /&gt;
&lt;br /&gt;
Configure LDAP plugin.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Simple Example settings ===&lt;br /&gt;
Ldap server e.g. ldap://ldap.mydomain.com: ldap://ldap.mydomain.com&lt;br /&gt;
Port number (default when omitted is 389):&lt;br /&gt;
LDAP version (LDAPv2 = 2), e.g. 3: 3&lt;br /&gt;
Username prefix cn= or uid=: cn=&lt;br /&gt;
Username suffix e.g. @mydomain.com or remaining part of ldap query: ,OU=people,DC=mydomain,DC=com&lt;br /&gt;
Create a LimeSurvey administrator with the same name as a AD(active directory) user account.&lt;br /&gt;
Log in using the AD credentials(username and password).&lt;br /&gt;
&lt;br /&gt;
=== Example settings AD2008 &amp;amp; 2.05+ ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Settings working with Active Directory 2008 and 2.05+ (build 140520) with AuthLDAP plugin &#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==== Authentication with LDAP and &#039;&#039;userPrincipalName&#039;&#039; attribute ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: Authentication with &#039;&#039;userPrincipalName&#039;&#039; attribute (ie: firstname.lastname@example.intra). Create a LimeSurvey user with the same name as a AD(active directory) user account :&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Username&#039;&#039;: &#039;&#039;&#039;firstname.lastname@example.intra&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Email&#039;&#039;: &#039;&#039;&#039;firstname.lastname@example.intra&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Full name&#039;&#039;: &#039;&#039;&#039;Firstname LASTNAME&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Then configure the plugin : &#039;&#039;Plugin Manager &amp;gt; LDAP &amp;gt; Configure&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Ldap server e.g. ldap://ldap.example.intra&#039;&#039;: &#039;&#039;&#039;ldap://ldap.example.intra&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Port number (default when omitted is 389)&#039;&#039;: &#039;&#039;&#039;389&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;LDAP version (LDAPv2 = 2), e.g. 3&#039;&#039;: &#039;&#039;&#039;LDAPv3&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Username prefix cn= or uid=: cn=&#039;&#039;: &#039;&#039;&#039;empty&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Username suffix e.g. @example.intra or remaining part of ldap query&#039;&#039;: &#039;&#039;&#039;empty&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Log in using the AD credentials (username: &#039;&#039;&#039;firstname.lastname@example.intra&#039;&#039;&#039; and password).&lt;br /&gt;
&lt;br /&gt;
==== Authentication with LDAP and &#039;&#039;sAMaccountName&#039;&#039; attribute ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: Authentication with &#039;&#039;sAMaccountName&#039;&#039; attribute (ie: firstname.lastname). Create a LimeSurvey user with the same name as a AD(active directory) user account :&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Username&#039;&#039;: &#039;&#039;&#039;firstname.lastname&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Email&#039;&#039;: &#039;&#039;&#039;firstname.lastname@example.intra&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Full name&#039;&#039;: &#039;&#039;&#039;Firstname LASTNAME&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Then configure the plugin : &#039;&#039;Plugin Manager &amp;gt; LDAP &amp;gt; Configure&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Ldap server e.g. ldap://ldap.example.com&#039;&#039;: &#039;&#039;&#039;ldap://ldap.example.intra&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Port number (default when omitted is 389)&#039;&#039;: &#039;&#039;&#039;389&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;LDAP version (LDAPv2 = 2), e.g. 3&#039;&#039;: &#039;&#039;&#039;LDAPv3&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Username prefix cn= or uid=: cn=&#039;&#039;: &#039;&#039;&#039;empty&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Username suffix e.g. @example.com or remaining part of ldap query&#039;&#039;: &#039;&#039;&#039;@example.intra&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Log in using the AD credentials (username: &#039;&#039;&#039;firstname.lastname&#039;&#039;&#039; and password).&lt;br /&gt;
&lt;br /&gt;
==== Authentication with LDAPS and &#039;&#039;sAMaccountName&#039;&#039; attribute ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: Authentication with &#039;&#039;sAMaccountName&#039;&#039; attribute (ie: firstname.lastname). Create a LimeSurvey user with the same name as a AD(active directory) user account :&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Username&#039;&#039;: &#039;&#039;&#039;firstname.lastname&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Email&#039;&#039;: &#039;&#039;&#039;firstname.lastname@example.intra&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Full name&#039;&#039;: &#039;&#039;&#039;Firstname LASTNAME&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Then configure the plugin : &#039;&#039;Plugin Manager &amp;gt; LDAP &amp;gt; Configure&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Ldap server e.g. ldap://ldap.example.com&#039;&#039;: &#039;&#039;&#039;ldaps://ldap.example.intra&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Port number (default when omitted is 389)&#039;&#039;: &#039;&#039;&#039;636&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;LDAP version (LDAPv2 = 2), e.g. 3&#039;&#039;: &#039;&#039;&#039;LDAPv3&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Username prefix cn= or uid=: cn=&#039;&#039;: &#039;&#039;&#039;empty&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Username suffix e.g. @example.intra or remaining part of ldap query&#039;&#039;: &#039;&#039;&#039;@example.intra&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Log in using the AD credentials (username: &#039;&#039;&#039;firstname.lastname&#039;&#039;&#039; and password).&lt;br /&gt;
&lt;br /&gt;
=== Example settings OpenLDAP &amp;amp; 2.05+ ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Settings working with OpenLDAP and 2.05+ (git version Feb. 2015) with AuthLDAP plugin &#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==== Authentication with LDAP and &#039;&#039;uid&#039;&#039; attribute ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: Authentication with &#039;&#039;uid&#039;&#039; attribute. Create a LimeSurvey user with the same name as a the LDAP user account.&lt;br /&gt;
&lt;br /&gt;
Then configure the plugin : &#039;&#039;Plugin Manager &amp;gt; LDAP &amp;gt; Configure&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Ldap server e.g. ldap://ldap.mydomain.com&#039;&#039;: &#039;&#039;&#039;ldap://ldap.mydomain.com&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;Port number (default when omitted is 389)&#039;&#039;: &#039;&#039;&#039;(389 or leave blank)&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;LDAP version (LDAPv2 = 2), e.g. 3&#039;&#039;: &#039;&#039;&#039;LDAPv3&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;Select true if referrals must be followed (use false for ActiveDirectory)&#039;&#039;: &#039;&#039;&#039;(leave blank)&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;Check to enable Start-TLS encryption When using LDAPv3&#039;&#039;: &#039;&#039;&#039;False&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;Select how to perform authentication&#039;&#039;: &#039;&#039;&#039;Search and bind&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;Attribute to compare to the given login can be uid, cn, mail, ...&#039;&#039;: &#039;&#039;&#039;uid&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;Base DN for the user search operation&#039;&#039;: &#039;&#039;&#039;ou=people,dc=mydomain,dc=com&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;Optional extra LDAP filter to be ANDed to the basic (searchuserattribute=username) filter. Don&#039;t forget the outmost enclosing parentheses&#039;&#039;: &#039;&#039;&#039;(leave blank)&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;Optional DN of the LDAP account used to search for the end-user&#039;s DN. An anonymous bind is performed if empty.&#039;&#039;: &#039;&#039;&#039;cn=admin,dc=mydomain,dc=com&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;Password of the LDAP account used to search for the end-user&#039;s DN if previoulsy set.&#039;&#039;: &#039;&#039;&#039;password&#039;&#039;&#039; (appears!)&lt;br /&gt;
* &#039;&#039;Check to make default authentication method&#039;&#039;: &#039;&#039;&#039;(as you wish)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Log in using the LDAP credentials (username: &#039;&#039;&#039;user&#039;&#039;&#039; and password).&lt;br /&gt;
&lt;br /&gt;
==== Authentication with OpenLDAP, &#039;&#039;uid&#039;&#039; attribute, and group restriction [2.62+] ====&lt;br /&gt;
&lt;br /&gt;
Some applications require a separate LDAP query (beyond the user search and bind to check password) to determine if the user has sufficient authorization. For example, let&#039;s assume that LDAP has a &amp;lt;code&amp;gt;Groups&amp;lt;/code&amp;gt; OU that includes an entry identified by &amp;lt;code&amp;gt;cn=limeusers&amp;lt;/code&amp;gt; and our policy is that for a user to be authorized to use LimeSurvey that entry must include an attribute of the form &amp;lt;code&amp;gt;memberUid=&amp;lt;i&amp;gt;username&amp;lt;/i&amp;gt;&amp;lt;/code&amp;gt; where &#039;&#039;username&#039;&#039; is the username (uid) entered by the user attempting to login. To configure LDAP for that, set up basic &#039;&#039;uid&#039;&#039; authentication as above and then set the following additional (optional) parameters:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Optional base DN for group restriction&#039;&#039;: &amp;lt;code&amp;gt;ou=Groups,dc=mydomain,dc=com&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;Optional filter for group restriction&#039;&#039;: &amp;lt;code&amp;gt;(&amp;amp;(cn=limeusers)(memberUid=$username))&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note:&lt;br /&gt;
# &amp;lt;code&amp;gt;$username&amp;lt;/code&amp;gt; is a magic value (in the context of the filter parameter) that is replaced by the username entered by the user when logging in.&lt;br /&gt;
# Although intended for testing group membership as above, this optional &amp;quot;group restriction&amp;quot; capability can be used to add any authorization check that can be expressed as a separate filtered search like this.&lt;br /&gt;
# Before specifying a group restriction this way, verify that basic LDAP authentication is working correctly.&lt;br /&gt;
# If either of the group restriction parameters is empty then the group restriction step will not be applied.&lt;br /&gt;
&lt;br /&gt;
== Webserver authentication ==&lt;br /&gt;
&lt;br /&gt;
This plugin leaves authentication to the webserver and reads the result from a configurable server setting. This method has been around for a while, and was configured from config.php. If you used this authentication, you should enable the plugin in the plugins menu and move your configuration from config.php to the plugin&#039;s settings. Feel free to contact the team via the bugtracker or irc-channel if it no longer functions the way it did before.&lt;br /&gt;
&lt;br /&gt;
[[Category:Plugins]]&lt;/div&gt;</summary>
		<author><name>LimeAJ</name></author>
	</entry>
	<entry>
		<id>https://www.limesurvey.org/manual/index.php?title=Authentication_plugins&amp;diff=76225</id>
		<title>Authentication plugins</title>
		<link rel="alternate" type="text/html" href="https://www.limesurvey.org/manual/index.php?title=Authentication_plugins&amp;diff=76225"/>
		<updated>2017-08-14T17:06:27Z</updated>

		<summary type="html">&lt;p&gt;LimeAJ: /* LDAP */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This is an overview of the authentication plugins currently shipped with LimeSurvey. If you want to extend or develop your own authentication plugin, please see [[Authentication_plugin development]]&lt;br /&gt;
&lt;br /&gt;
== Internal database ==&lt;br /&gt;
This plugin is the default and can not be disabled. It uses the built in LimeSurvey database. It is a fall-back mechanism so that you can always login to the installation when needed.&lt;br /&gt;
&lt;br /&gt;
== LDAP ==&lt;br /&gt;
By activating this plugin you can perform basic authentication against an LDAP server. Make sure your PHP configuration has LDAP support enabled.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Enabling and configuring settings for plugin AuthLDAP v2.05+&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Enable LDAP in PHP.INI.&lt;br /&gt;
Verify that [http://php.net/manual/en/function.phpinfo.php|phpinfo.php shows that LDAP is enabled].&lt;br /&gt;
Go to LimeSurvey Plugin Manager.&lt;br /&gt;
Configure LDAP plugin.&lt;br /&gt;
&lt;br /&gt;
=== Simple Example settings ===&lt;br /&gt;
Ldap server e.g. ldap://ldap.mydomain.com: ldap://ldap.mydomain.com&lt;br /&gt;
Port number (default when omitted is 389):&lt;br /&gt;
LDAP version (LDAPv2 = 2), e.g. 3: 3&lt;br /&gt;
Username prefix cn= or uid=: cn=&lt;br /&gt;
Username suffix e.g. @mydomain.com or remaining part of ldap query: ,OU=people,DC=mydomain,DC=com&lt;br /&gt;
Create a LimeSurvey administrator with the same name as a AD(active directory) user account.&lt;br /&gt;
Log in using the AD credentials(username and password).&lt;br /&gt;
&lt;br /&gt;
=== Example settings AD2008 &amp;amp; 2.05+ ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Settings working with Active Directory 2008 and 2.05+ (build 140520) with AuthLDAP plugin &#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==== Authentication with LDAP and &#039;&#039;userPrincipalName&#039;&#039; attribute ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: Authentication with &#039;&#039;userPrincipalName&#039;&#039; attribute (ie: firstname.lastname@example.intra). Create a LimeSurvey user with the same name as a AD(active directory) user account :&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Username&#039;&#039;: &#039;&#039;&#039;firstname.lastname@example.intra&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Email&#039;&#039;: &#039;&#039;&#039;firstname.lastname@example.intra&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Full name&#039;&#039;: &#039;&#039;&#039;Firstname LASTNAME&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Then configure the plugin : &#039;&#039;Plugin Manager &amp;gt; LDAP &amp;gt; Configure&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Ldap server e.g. ldap://ldap.example.intra&#039;&#039;: &#039;&#039;&#039;ldap://ldap.example.intra&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Port number (default when omitted is 389)&#039;&#039;: &#039;&#039;&#039;389&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;LDAP version (LDAPv2 = 2), e.g. 3&#039;&#039;: &#039;&#039;&#039;LDAPv3&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Username prefix cn= or uid=: cn=&#039;&#039;: &#039;&#039;&#039;empty&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Username suffix e.g. @example.intra or remaining part of ldap query&#039;&#039;: &#039;&#039;&#039;empty&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Log in using the AD credentials (username: &#039;&#039;&#039;firstname.lastname@example.intra&#039;&#039;&#039; and password).&lt;br /&gt;
&lt;br /&gt;
==== Authentication with LDAP and &#039;&#039;sAMaccountName&#039;&#039; attribute ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: Authentication with &#039;&#039;sAMaccountName&#039;&#039; attribute (ie: firstname.lastname). Create a LimeSurvey user with the same name as a AD(active directory) user account :&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Username&#039;&#039;: &#039;&#039;&#039;firstname.lastname&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Email&#039;&#039;: &#039;&#039;&#039;firstname.lastname@example.intra&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Full name&#039;&#039;: &#039;&#039;&#039;Firstname LASTNAME&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Then configure the plugin : &#039;&#039;Plugin Manager &amp;gt; LDAP &amp;gt; Configure&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Ldap server e.g. ldap://ldap.example.com&#039;&#039;: &#039;&#039;&#039;ldap://ldap.example.intra&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Port number (default when omitted is 389)&#039;&#039;: &#039;&#039;&#039;389&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;LDAP version (LDAPv2 = 2), e.g. 3&#039;&#039;: &#039;&#039;&#039;LDAPv3&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Username prefix cn= or uid=: cn=&#039;&#039;: &#039;&#039;&#039;empty&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Username suffix e.g. @example.com or remaining part of ldap query&#039;&#039;: &#039;&#039;&#039;@example.intra&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Log in using the AD credentials (username: &#039;&#039;&#039;firstname.lastname&#039;&#039;&#039; and password).&lt;br /&gt;
&lt;br /&gt;
==== Authentication with LDAPS and &#039;&#039;sAMaccountName&#039;&#039; attribute ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: Authentication with &#039;&#039;sAMaccountName&#039;&#039; attribute (ie: firstname.lastname). Create a LimeSurvey user with the same name as a AD(active directory) user account :&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Username&#039;&#039;: &#039;&#039;&#039;firstname.lastname&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Email&#039;&#039;: &#039;&#039;&#039;firstname.lastname@example.intra&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Full name&#039;&#039;: &#039;&#039;&#039;Firstname LASTNAME&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Then configure the plugin : &#039;&#039;Plugin Manager &amp;gt; LDAP &amp;gt; Configure&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Ldap server e.g. ldap://ldap.example.com&#039;&#039;: &#039;&#039;&#039;ldaps://ldap.example.intra&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Port number (default when omitted is 389)&#039;&#039;: &#039;&#039;&#039;636&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;LDAP version (LDAPv2 = 2), e.g. 3&#039;&#039;: &#039;&#039;&#039;LDAPv3&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Username prefix cn= or uid=: cn=&#039;&#039;: &#039;&#039;&#039;empty&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Username suffix e.g. @example.intra or remaining part of ldap query&#039;&#039;: &#039;&#039;&#039;@example.intra&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Log in using the AD credentials (username: &#039;&#039;&#039;firstname.lastname&#039;&#039;&#039; and password).&lt;br /&gt;
&lt;br /&gt;
=== Example settings OpenLDAP &amp;amp; 2.05+ ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Settings working with OpenLDAP and 2.05+ (git version Feb. 2015) with AuthLDAP plugin &#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==== Authentication with LDAP and &#039;&#039;uid&#039;&#039; attribute ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: Authentication with &#039;&#039;uid&#039;&#039; attribute. Create a LimeSurvey user with the same name as a the LDAP user account.&lt;br /&gt;
&lt;br /&gt;
Then configure the plugin : &#039;&#039;Plugin Manager &amp;gt; LDAP &amp;gt; Configure&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Ldap server e.g. ldap://ldap.mydomain.com&#039;&#039;: &#039;&#039;&#039;ldap://ldap.mydomain.com&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;Port number (default when omitted is 389)&#039;&#039;: &#039;&#039;&#039;(389 or leave blank)&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;LDAP version (LDAPv2 = 2), e.g. 3&#039;&#039;: &#039;&#039;&#039;LDAPv3&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;Select true if referrals must be followed (use false for ActiveDirectory)&#039;&#039;: &#039;&#039;&#039;(leave blank)&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;Check to enable Start-TLS encryption When using LDAPv3&#039;&#039;: &#039;&#039;&#039;False&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;Select how to perform authentication&#039;&#039;: &#039;&#039;&#039;Search and bind&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;Attribute to compare to the given login can be uid, cn, mail, ...&#039;&#039;: &#039;&#039;&#039;uid&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;Base DN for the user search operation&#039;&#039;: &#039;&#039;&#039;ou=people,dc=mydomain,dc=com&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;Optional extra LDAP filter to be ANDed to the basic (searchuserattribute=username) filter. Don&#039;t forget the outmost enclosing parentheses&#039;&#039;: &#039;&#039;&#039;(leave blank)&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;Optional DN of the LDAP account used to search for the end-user&#039;s DN. An anonymous bind is performed if empty.&#039;&#039;: &#039;&#039;&#039;cn=admin,dc=mydomain,dc=com&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;Password of the LDAP account used to search for the end-user&#039;s DN if previoulsy set.&#039;&#039;: &#039;&#039;&#039;password&#039;&#039;&#039; (appears!)&lt;br /&gt;
* &#039;&#039;Check to make default authentication method&#039;&#039;: &#039;&#039;&#039;(as you wish)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Log in using the LDAP credentials (username: &#039;&#039;&#039;user&#039;&#039;&#039; and password).&lt;br /&gt;
&lt;br /&gt;
==== Authentication with OpenLDAP, &#039;&#039;uid&#039;&#039; attribute, and group restriction [2.62+] ====&lt;br /&gt;
&lt;br /&gt;
Some applications require a separate LDAP query (beyond the user search and bind to check password) to determine if the user has sufficient authorization. For example, let&#039;s assume that LDAP has a &amp;lt;code&amp;gt;Groups&amp;lt;/code&amp;gt; OU that includes an entry identified by &amp;lt;code&amp;gt;cn=limeusers&amp;lt;/code&amp;gt; and our policy is that for a user to be authorized to use LimeSurvey that entry must include an attribute of the form &amp;lt;code&amp;gt;memberUid=&amp;lt;i&amp;gt;username&amp;lt;/i&amp;gt;&amp;lt;/code&amp;gt; where &#039;&#039;username&#039;&#039; is the username (uid) entered by the user attempting to login. To configure LDAP for that, set up basic &#039;&#039;uid&#039;&#039; authentication as above and then set the following additional (optional) parameters:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Optional base DN for group restriction&#039;&#039;: &amp;lt;code&amp;gt;ou=Groups,dc=mydomain,dc=com&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;Optional filter for group restriction&#039;&#039;: &amp;lt;code&amp;gt;(&amp;amp;(cn=limeusers)(memberUid=$username))&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note:&lt;br /&gt;
# &amp;lt;code&amp;gt;$username&amp;lt;/code&amp;gt; is a magic value (in the context of the filter parameter) that is replaced by the username entered by the user when logging in.&lt;br /&gt;
# Although intended for testing group membership as above, this optional &amp;quot;group restriction&amp;quot; capability can be used to add any authorization check that can be expressed as a separate filtered search like this.&lt;br /&gt;
# Before specifying a group restriction this way, verify that basic LDAP authentication is working correctly.&lt;br /&gt;
# If either of the group restriction parameters is empty then the group restriction step will not be applied.&lt;br /&gt;
&lt;br /&gt;
== Webserver authentication ==&lt;br /&gt;
&lt;br /&gt;
This plugin leaves authentication to the webserver and reads the result from a configurable server setting. This method has been around for a while, and was configured from config.php. If you used this authentication, you should enable the plugin in the plugins menu and move your configuration from config.php to the plugin&#039;s settings. Feel free to contact the team via the bugtracker or irc-channel if it no longer functions the way it did before.&lt;br /&gt;
&lt;br /&gt;
[[Category:Plugins]]&lt;/div&gt;</summary>
		<author><name>LimeAJ</name></author>
	</entry>
	<entry>
		<id>https://www.limesurvey.org/manual/index.php?title=Authentication_plugins&amp;diff=76222</id>
		<title>Authentication plugins</title>
		<link rel="alternate" type="text/html" href="https://www.limesurvey.org/manual/index.php?title=Authentication_plugins&amp;diff=76222"/>
		<updated>2017-08-14T14:53:43Z</updated>

		<summary type="html">&lt;p&gt;LimeAJ: /* Internal database */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This is an overview of the authentication plugins currently shipped with LimeSurvey. If you want to extend or develop your own authentication plugin, please see [[Authentication_plugin development]]&lt;br /&gt;
&lt;br /&gt;
== Internal database ==&lt;br /&gt;
This plugin is the default and can not be disabled. It uses the built in LimeSurvey database. It is a fall-back mechanism so that you can always login to the installation when needed.&lt;br /&gt;
&lt;br /&gt;
== LDAP ==&lt;br /&gt;
By activating this plugin you can perform basic authentication against an LDAP server. Make sure your PHP configuration has LDAP support enabled.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Enabling and configuring settings for plugin AuthLDAP v2.05+&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Enable LDAP in PHP.INI.&lt;br /&gt;
Verify that phpinfo.php shows that LDAP is enabled.&lt;br /&gt;
Go to LimeSurvey Plugin Manager.&lt;br /&gt;
Configure LDAP plugin.&lt;br /&gt;
&lt;br /&gt;
=== Simple Example settings ===&lt;br /&gt;
Ldap server e.g. ldap://ldap.mydomain.com: ldap://ldap.mydomain.com&lt;br /&gt;
Port number (default when omitted is 389):&lt;br /&gt;
LDAP version (LDAPv2 = 2), e.g. 3: 3&lt;br /&gt;
Username prefix cn= or uid=: cn=&lt;br /&gt;
Username suffix e.g. @mydomain.com or remaining part of ldap query: ,OU=people,DC=mydomain,DC=com&lt;br /&gt;
Create a LimeSurvey administrator with the same name as a AD(active directory) user account.&lt;br /&gt;
Log in using the AD credentials(username and password).&lt;br /&gt;
&lt;br /&gt;
=== Example settings AD2008 &amp;amp; 2.05+ ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Settings working with Active Directory 2008 and 2.05+ (build 140520) with AuthLDAP plugin &#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==== Authentication with LDAP and &#039;&#039;userPrincipalName&#039;&#039; attribute ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: Authentication with &#039;&#039;userPrincipalName&#039;&#039; attribute (ie: firstname.lastname@example.intra). Create a LimeSurvey user with the same name as a AD(active directory) user account :&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Username&#039;&#039;: &#039;&#039;&#039;firstname.lastname@example.intra&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Email&#039;&#039;: &#039;&#039;&#039;firstname.lastname@example.intra&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Full name&#039;&#039;: &#039;&#039;&#039;Firstname LASTNAME&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Then configure the plugin : &#039;&#039;Plugin Manager &amp;gt; LDAP &amp;gt; Configure&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Ldap server e.g. ldap://ldap.example.intra&#039;&#039;: &#039;&#039;&#039;ldap://ldap.example.intra&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Port number (default when omitted is 389)&#039;&#039;: &#039;&#039;&#039;389&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;LDAP version (LDAPv2 = 2), e.g. 3&#039;&#039;: &#039;&#039;&#039;LDAPv3&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Username prefix cn= or uid=: cn=&#039;&#039;: &#039;&#039;&#039;empty&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Username suffix e.g. @example.intra or remaining part of ldap query&#039;&#039;: &#039;&#039;&#039;empty&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Log in using the AD credentials (username: &#039;&#039;&#039;firstname.lastname@example.intra&#039;&#039;&#039; and password).&lt;br /&gt;
&lt;br /&gt;
==== Authentication with LDAP and &#039;&#039;sAMaccountName&#039;&#039; attribute ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: Authentication with &#039;&#039;sAMaccountName&#039;&#039; attribute (ie: firstname.lastname). Create a LimeSurvey user with the same name as a AD(active directory) user account :&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Username&#039;&#039;: &#039;&#039;&#039;firstname.lastname&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Email&#039;&#039;: &#039;&#039;&#039;firstname.lastname@example.intra&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Full name&#039;&#039;: &#039;&#039;&#039;Firstname LASTNAME&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Then configure the plugin : &#039;&#039;Plugin Manager &amp;gt; LDAP &amp;gt; Configure&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Ldap server e.g. ldap://ldap.example.com&#039;&#039;: &#039;&#039;&#039;ldap://ldap.example.intra&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Port number (default when omitted is 389)&#039;&#039;: &#039;&#039;&#039;389&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;LDAP version (LDAPv2 = 2), e.g. 3&#039;&#039;: &#039;&#039;&#039;LDAPv3&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Username prefix cn= or uid=: cn=&#039;&#039;: &#039;&#039;&#039;empty&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Username suffix e.g. @example.com or remaining part of ldap query&#039;&#039;: &#039;&#039;&#039;@example.intra&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Log in using the AD credentials (username: &#039;&#039;&#039;firstname.lastname&#039;&#039;&#039; and password).&lt;br /&gt;
&lt;br /&gt;
==== Authentication with LDAPS and &#039;&#039;sAMaccountName&#039;&#039; attribute ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: Authentication with &#039;&#039;sAMaccountName&#039;&#039; attribute (ie: firstname.lastname). Create a LimeSurvey user with the same name as a AD(active directory) user account :&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Username&#039;&#039;: &#039;&#039;&#039;firstname.lastname&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Email&#039;&#039;: &#039;&#039;&#039;firstname.lastname@example.intra&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Full name&#039;&#039;: &#039;&#039;&#039;Firstname LASTNAME&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Then configure the plugin : &#039;&#039;Plugin Manager &amp;gt; LDAP &amp;gt; Configure&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Ldap server e.g. ldap://ldap.example.com&#039;&#039;: &#039;&#039;&#039;ldaps://ldap.example.intra&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Port number (default when omitted is 389)&#039;&#039;: &#039;&#039;&#039;636&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;LDAP version (LDAPv2 = 2), e.g. 3&#039;&#039;: &#039;&#039;&#039;LDAPv3&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Username prefix cn= or uid=: cn=&#039;&#039;: &#039;&#039;&#039;empty&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Username suffix e.g. @example.intra or remaining part of ldap query&#039;&#039;: &#039;&#039;&#039;@example.intra&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Log in using the AD credentials (username: &#039;&#039;&#039;firstname.lastname&#039;&#039;&#039; and password).&lt;br /&gt;
&lt;br /&gt;
=== Example settings OpenLDAP &amp;amp; 2.05+ ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Settings working with OpenLDAP and 2.05+ (git version Feb. 2015) with AuthLDAP plugin &#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==== Authentication with LDAP and &#039;&#039;uid&#039;&#039; attribute ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note&#039;&#039;&#039;: Authentication with &#039;&#039;uid&#039;&#039; attribute. Create a LimeSurvey user with the same name as a the LDAP user account.&lt;br /&gt;
&lt;br /&gt;
Then configure the plugin : &#039;&#039;Plugin Manager &amp;gt; LDAP &amp;gt; Configure&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Ldap server e.g. ldap://ldap.mydomain.com&#039;&#039;: &#039;&#039;&#039;ldap://ldap.mydomain.com&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;Port number (default when omitted is 389)&#039;&#039;: &#039;&#039;&#039;(389 or leave blank)&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;LDAP version (LDAPv2 = 2), e.g. 3&#039;&#039;: &#039;&#039;&#039;LDAPv3&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;Select true if referrals must be followed (use false for ActiveDirectory)&#039;&#039;: &#039;&#039;&#039;(leave blank)&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;Check to enable Start-TLS encryption When using LDAPv3&#039;&#039;: &#039;&#039;&#039;False&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;Select how to perform authentication&#039;&#039;: &#039;&#039;&#039;Search and bind&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;Attribute to compare to the given login can be uid, cn, mail, ...&#039;&#039;: &#039;&#039;&#039;uid&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;Base DN for the user search operation&#039;&#039;: &#039;&#039;&#039;ou=people,dc=mydomain,dc=com&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;Optional extra LDAP filter to be ANDed to the basic (searchuserattribute=username) filter. Don&#039;t forget the outmost enclosing parentheses&#039;&#039;: &#039;&#039;&#039;(leave blank)&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;Optional DN of the LDAP account used to search for the end-user&#039;s DN. An anonymous bind is performed if empty.&#039;&#039;: &#039;&#039;&#039;cn=admin,dc=mydomain,dc=com&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;Password of the LDAP account used to search for the end-user&#039;s DN if previoulsy set.&#039;&#039;: &#039;&#039;&#039;password&#039;&#039;&#039; (appears!)&lt;br /&gt;
* &#039;&#039;Check to make default authentication method&#039;&#039;: &#039;&#039;&#039;(as you wish)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Log in using the LDAP credentials (username: &#039;&#039;&#039;user&#039;&#039;&#039; and password).&lt;br /&gt;
&lt;br /&gt;
==== Authentication with OpenLDAP, &#039;&#039;uid&#039;&#039; attribute, and group restriction [2.62+] ====&lt;br /&gt;
&lt;br /&gt;
Some applications require a separate LDAP query (beyond the user search and bind to check password) to determine if the user has sufficient authorization. For example, let&#039;s assume that LDAP has a &amp;lt;code&amp;gt;Groups&amp;lt;/code&amp;gt; OU that includes an entry identified by &amp;lt;code&amp;gt;cn=limeusers&amp;lt;/code&amp;gt; and our policy is that for a user to be authorized to use LimeSurvey that entry must include an attribute of the form &amp;lt;code&amp;gt;memberUid=&amp;lt;i&amp;gt;username&amp;lt;/i&amp;gt;&amp;lt;/code&amp;gt; where &#039;&#039;username&#039;&#039; is the username (uid) entered by the user attempting to login. To configure LDAP for that, set up basic &#039;&#039;uid&#039;&#039; authentication as above and then set the following additional (optional) parameters:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Optional base DN for group restriction&#039;&#039;: &amp;lt;code&amp;gt;ou=Groups,dc=mydomain,dc=com&amp;lt;/code&amp;gt;&lt;br /&gt;
* &#039;&#039;Optional filter for group restriction&#039;&#039;: &amp;lt;code&amp;gt;(&amp;amp;(cn=limeusers)(memberUid=$username))&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note:&lt;br /&gt;
# &amp;lt;code&amp;gt;$username&amp;lt;/code&amp;gt; is a magic value (in the context of the filter parameter) that is replaced by the username entered by the user when logging in.&lt;br /&gt;
# Although intended for testing group membership as above, this optional &amp;quot;group restriction&amp;quot; capability can be used to add any authorization check that can be expressed as a separate filtered search like this.&lt;br /&gt;
# Before specifying a group restriction this way, verify that basic LDAP authentication is working correctly.&lt;br /&gt;
# If either of the group restriction parameters is empty then the group restriction step will not be applied.&lt;br /&gt;
&lt;br /&gt;
== Webserver authentication ==&lt;br /&gt;
&lt;br /&gt;
This plugin leaves authentication to the webserver and reads the result from a configurable server setting. This method has been around for a while, and was configured from config.php. If you used this authentication, you should enable the plugin in the plugins menu and move your configuration from config.php to the plugin&#039;s settings. Feel free to contact the team via the bugtracker or irc-channel if it no longer functions the way it did before.&lt;br /&gt;
&lt;br /&gt;
[[Category:Plugins]]&lt;/div&gt;</summary>
		<author><name>LimeAJ</name></author>
	</entry>
	<entry>
		<id>https://www.limesurvey.org/manual/index.php?title=Expression_Manager&amp;diff=74066</id>
		<title>Expression Manager</title>
		<link rel="alternate" type="text/html" href="https://www.limesurvey.org/manual/index.php?title=Expression_Manager&amp;diff=74066"/>
		<updated>2017-07-28T20:38:00Z</updated>

		<summary type="html">&lt;p&gt;LimeAJ: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;languages /&amp;gt; &amp;lt;translate&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:1--&amp;gt;&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:2--&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;simplebox&amp;quot;&amp;gt; Note: This feature is only available in LimeSurvey 1.92 or later. &amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Quick Start Tutorial= &amp;lt;!--T:3--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Overview== &amp;lt;!--T:4--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:5--&amp;gt;&lt;br /&gt;
When customizing your surveys, you typically need a way to specify the following:&lt;br /&gt;
#&#039;&#039;&#039;Navigation/Branching&#039;&#039;&#039; - letting a subject&#039;s answers change the order in which questions are asked&lt;br /&gt;
#&#039;&#039;&#039;Tailoring/Piping&#039;&#039;&#039; - how to phrase the question (such as referring to prior answers, or conjugating sentences based upon the number or gender of your subjects), or how to generate custom reports (like assessment scores or tailored advice).&lt;br /&gt;
#&#039;&#039;&#039;Validation&#039;&#039;&#039; - ensuring that answers pass certain criteria, like min and max values, or matching an input pattern&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:6--&amp;gt;&lt;br /&gt;
Expression Manager (EM) provides an intuitive way to specifying the logic for each of those features.  Nearly anything that you can write as a standard mathematical equation is a valid expression, even if you are calling functions.  EM currently provides access to 70 functions, and can be easily extended to support more.  It also lets you access your variables using human-readable variable names (rather than SGQA names).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:7--&amp;gt;&lt;br /&gt;
The following sections show the main places where Expression Manager is used&lt;br /&gt;
&lt;br /&gt;
==Relevance (Controlling Navigation/Branching)== &amp;lt;!--T:8--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:9--&amp;gt;&lt;br /&gt;
Some surveys use &amp;quot;Goto Logic&amp;quot;, such that if you answer Question 1 with option C, then jump to Question 5. This approach is very limiting, since is hard to validate, and easily breaks if you have to re-order questions.  EM uses a Boolean relevance equation to specify all of the conditions under which a question might be valid.  If the question is relevant, then the question is asked, otherwise it is Not Applicable, and the value NULL is stored in the database.  This is similar to what can be done via the Conditions editor, but EM lets you easily specify much more complex and powerful criteria (and lets you use the variable name rather than SGQA naming).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:10--&amp;gt;&lt;br /&gt;
This image shows one way to review the relevance logic for a survey.  It computes Body Mass Index.  The relevance equation is shown in square bracket right after the variable name (which is in green).  So, the relevance of weight, weight_units, height and height_units are all 1, meaning that those questions are always asked.  However, the relevance for BMI is {!is_empty(height) and !is_empty(weight)}, which means that BMI will only be computed if the subject enters a value for both height and weight (thereby avoiding the risk of a divide by zero error).  Also, the Report question is only shown if the subject answers all four main questions (height, height_units, weight, weight_units).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:11--&amp;gt;&lt;br /&gt;
[[File:tutorial1.jpg]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:12--&amp;gt;&lt;br /&gt;
Relevance is shown and editable in the following places:&lt;br /&gt;
&lt;br /&gt;
===Viewing / Editing Question-Level Relevance=== &amp;lt;!--T:13--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:14--&amp;gt;&lt;br /&gt;
This equation computes the Body Mass Index (BMI).  It is only asked if the person first enters their height and weight.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:15--&amp;gt;&lt;br /&gt;
[[File:tutorial2.jpg]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:16--&amp;gt;&lt;br /&gt;
This is the edit screen for the BMI question.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:17--&amp;gt;&lt;br /&gt;
[[File:tutorial3.jpg]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:18--&amp;gt;&lt;br /&gt;
Note that you do not use the curly braces when you enter a Relevance Equation.&lt;br /&gt;
&lt;br /&gt;
===Viewing / Editing Group-Level Relevance=== &amp;lt;!--T:19--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:20--&amp;gt;&lt;br /&gt;
This is a sample census survey.  The first page asks how many people live with you and stores that in the &amp;quot;cohabs&amp;quot; variable.  This page is only shown if you have more than one cohabitant (so it is shown for the second person cohabitating with you), and also only shows if you specified how Person One is related to you (p1_rel).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:21--&amp;gt;&lt;br /&gt;
[[File:tutorial4.jpg]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:22--&amp;gt;&lt;br /&gt;
As you can see, the group also has question-level relevance criteria, such that each question only appears once you have answered the question before it (e.g. {!is_empty(p1_sex)}).  EM combines the Group and Question-level relevance for you.  Questions in a group are only asked  if the group as a whole is relevant.  Then, only the subset of questions within the group that are relevant are asked.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:23--&amp;gt;&lt;br /&gt;
Here is the screen for editing the group-level relevance for that question:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:24--&amp;gt;&lt;br /&gt;
[[File:tutorial5.jpg]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:25--&amp;gt;&lt;br /&gt;
Note that you do not use the curly braces when you enter a Relevance Equation.&lt;br /&gt;
&lt;br /&gt;
==Tailoring/Piping== &amp;lt;!--T:26--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:27--&amp;gt;&lt;br /&gt;
EM lets you easily do simple and complex conditional tailoring of your questions.  Sometimes you just need simple substitution, like saying, &amp;quot;You said you purchased &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;Product].  What did you like best about it?&amp;quot;.  Sometimes you need conditional substitution like &amp;quot;&amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;Mr./Mrs.] &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;LastName], would you be willing to complete our survey?&amp;quot;.  In this case,  you want to use Mr. or Mrs. based upon the person&#039;s gender.  Other times you need even more complex substitution (such as based upon a mathematical computation).  EM supports each of these types of tailoring/piping.&lt;br /&gt;
&lt;br /&gt;
===Conditional Equations=== &amp;lt;!--T:28--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:29--&amp;gt;&lt;br /&gt;
The Body Mass Index example shows the ability to compute a person&#039;s BMI, even while letting them enter their height in weight in metric or non-metric units.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:30--&amp;gt;&lt;br /&gt;
[[File:tailoring7.jpg]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:31--&amp;gt;&lt;br /&gt;
Here weight_kg is {if(weight_units == &#039;kg&#039;, weight, weight * .453592)}.  This if() function means that if the subject entered the weight using kilograms, use that value, otherwise multiple the entered value (which was in pounds) by .453592 to convert it to kilograms.  The height_m variable uses a similar approach to compute the person&#039;s height in meters, even if he entered his height in inches.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:32--&amp;gt;&lt;br /&gt;
BMI computes the weight formula as {weight_kg / (height_m * height_m)}.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:33--&amp;gt;&lt;br /&gt;
Lastly, the report conditionally tailors the message for the subject, telling him what he entered. (&amp;quot;You said you are 2 meters tall and weight 70 kg.&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:34--&amp;gt;&lt;br /&gt;
Although not well shown in the above image, weight_status uses nested if() statements to categorize the person as underweight to severely obese.  You can see its equation in the Show Logic View&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:35--&amp;gt;&lt;br /&gt;
[[File:tailoring8.jpg]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:36--&amp;gt;&lt;br /&gt;
From the edit window for this question, you can see two things:&lt;br /&gt;
#Tailoring must surround expressions with Curly Braces&lt;br /&gt;
#Expressions can span multiple lines if, as in this case, you want to make it easier to read the nested conditional logic.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:37--&amp;gt;&lt;br /&gt;
[[File:tailoring9.jpg]]&lt;br /&gt;
&lt;br /&gt;
===Tailored Questions, Answers, and Reports=== &amp;lt;!--T:38--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:39--&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;simplebox&amp;quot;&amp;gt;Note: Dynamic tailoring may not work if answer options are made available in select boxes on the same question page. This results from the fact that tailoring inserts a &amp;lt;nowiki&amp;gt;&amp;lt;span&amp;gt;&amp;lt;/nowiki&amp;gt; tag which is not valid inside select options.&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:40--&amp;gt;&lt;br /&gt;
This example shows the BMI report.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:41--&amp;gt;&lt;br /&gt;
[[File:tailoring10.jpg]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:42--&amp;gt;&lt;br /&gt;
Here is the edit window for the same question.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:43--&amp;gt;&lt;br /&gt;
[[File:tailoring11.jpg]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:44--&amp;gt;&lt;br /&gt;
As you can see, anything in curly braces is treated as an expression, so is syntax-highlighted (color coded) in the prior image.  If you had any typos (such as misspelled or undefined variable names or functions), EM would show an error, such as this, showing that height_unit is an undefined variable name (it is actually height_units), and rnd() is an undefined function (the proper function name is round()).  In both cases, the errors are surrounded by a red box to make it easier to spot and fix them.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:45--&amp;gt;&lt;br /&gt;
[[File:tailoring12.jpg]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:46--&amp;gt;&lt;br /&gt;
You can also see that you can quickly create complex reports, such as a table of entered values or tailored advice.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:47--&amp;gt;&lt;br /&gt;
Please remember that all tailoring must surround expressions with Curly Braces, so that LimeSurvey knows which parts of the question are free text and which should be parsed through Expression Manager.&lt;br /&gt;
&lt;br /&gt;
==Validation== &amp;lt;!--T:48--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:49--&amp;gt;&lt;br /&gt;
EM controls how most of the advanced question options work.  These control aspects like min/max numbers of answers; min/max individual values; min/max sum values; and checking that entered values match specified string patterns.  You continue to enter those advanced question options as usual.  However, now any value in one of those fields is considered an expression, so you can have min/max criteria with complex conditional relationships to other questions.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:50--&amp;gt;&lt;br /&gt;
In all of these cases, since the advanced question option is always considered an expression, you do not use curly braces when specifying it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:51--&amp;gt;&lt;br /&gt;
The [[Expression Manager Sample Surveys|Sample Surveys]] pages shows many working examples of using expressions for validations.&lt;br /&gt;
&lt;br /&gt;
=Introduction= &amp;lt;!--T:52--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:53--&amp;gt;&lt;br /&gt;
LimeSurvey uses the new Expression Manager (EM) module which will let LimeSurvey support more complex branching, assessments, validation, and tailoring.  It will replace how LimeSurvey manages Replacements, Conditions, and Assessments on the back-end.  It will also speed up processing considerably since it eliminates most run-time database reads.  EM was developed by Dr. Thomas White (TMSWhite).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:54--&amp;gt;&lt;br /&gt;
This wiki page is the definitive reference for Expression Manager syntax and functionality.&lt;br /&gt;
&lt;br /&gt;
==Key Definitions== &amp;lt;!--T:55--&amp;gt;&lt;br /&gt;
#&#039;&#039;&#039;Expression&#039;&#039;&#039;:  Anything surrounded by curly braces&lt;br /&gt;
#*As long as there is no white space immediately after the opening brace or before the closing curly brace&lt;br /&gt;
#*The contents of Expressions are evaluted by EM, so they can contain mathematical formulas, functions, and complex string and date processing.&lt;br /&gt;
#&#039;&#039;&#039;Tailoring&#039;&#039;&#039;: Sometimes called &amp;quot;piping&amp;quot;, this is the process of conditionally modifying text&lt;br /&gt;
#*You have access to all &#039;replacement fields&#039;, TOKENs, and INSERTANS values&lt;br /&gt;
#*You also have easier access to questions, answers, and their properties.&lt;br /&gt;
#&#039;&#039;&#039;Relevance&#039;&#039;&#039; Equation:  A new question attribute controlling question visiblity&lt;br /&gt;
#*If there is a relevance equation, then the question is only shown if the relevance evaluates to true.&lt;br /&gt;
#*Internally, all array_filter and array_filter_exclude commands become sub-question-level relevance&lt;br /&gt;
#&#039;&#039;&#039;Equation&#039;&#039;&#039; Question Type:  A new question type that saves calculations or reports to the database&lt;br /&gt;
#*It is like a Boilerplate question, but its contents are saved to the database even if you set &amp;quot;Always Hide this Question&amp;quot;&lt;br /&gt;
#&#039;&#039;&#039;Question Code&#039;&#039;&#039;:  This is the preferred variable name for EM&lt;br /&gt;
#*This can be a descriptive name indicating the purpose of the question, making it easier to read complex logic&lt;br /&gt;
#*Valid question codes should NOT start with a number, so when using the question code to number your questions, simply use &amp;quot;q1&amp;quot;, or &amp;quot;q1a&amp;quot; or &amp;quot;g1q2&amp;quot;.&lt;br /&gt;
#*This is what currently becomes the variable name if you export data to SPSS or R, so if you do statistical analysis, you probably already made this unique.&lt;br /&gt;
&lt;br /&gt;
==Do I have to use EM?== &amp;lt;!--T:56--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:57--&amp;gt;&lt;br /&gt;
The short answer is No (but also yes).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:58--&amp;gt;&lt;br /&gt;
EM is fully backwards-compatible with existing surveys.  So, if you are happy to use Conditions and Assessments in the style that LimeSurvey used in versions &amp;lt;= 1.91+, you can continue to do so.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:59--&amp;gt;&lt;br /&gt;
However, EM completely replaces how LimeSurvey internally deals with Conditions.  Although you can still use the Conditions Editor to create and manage conditions, LimeSurvey 1.92 will convert those to the equivalent Relevance Equations.  As part of the upgrade, LimeSurvey 1.92 will auto-convert all existing Conditions to Relevance Equations.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:60--&amp;gt;&lt;br /&gt;
This should give you the best of both worlds - you can continue using LimeSurvey as you are used to, but will see the Relevance Equation equivalent so you can gradually migrate to Relevance Equations directly whenever you see fit.&lt;br /&gt;
&lt;br /&gt;
==Can I mix use of Conditions and Relevance?== &amp;lt;!--T:61--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:62--&amp;gt;&lt;br /&gt;
Yes. You can use the Conditions editor for some questions and the Relevance editor for others.  Conditions are auto-converted to Relevance when you save the question.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:63--&amp;gt;&lt;br /&gt;
Note, we assume that if you are using the Conditions editor, that you want those Conditions to over-write any manually entered Relevance equation.  So, if you have existing Conditions and want to manually edit the Relevance, please delete the Conditions for that question first.  Specifically, copy the generated relevance equation to a text editor, use the Conditions menu to delete all of the conditions for that question (which will also delete the relevance), then edit the question and paste the generated relevance equation from the text editor back into the relevance field for that question (and save the question).  If there is enough demand for deleting conditions without deleting the generated relevance equation, we could add a bulk conversion process.&lt;br /&gt;
&lt;br /&gt;
==How should I choose between Conditions and Relevance?== &amp;lt;!--T:64--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:65--&amp;gt;&lt;br /&gt;
Here is a list of pros and cons of each style:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:66--&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Style!!Pros!!Cons&lt;br /&gt;
|-&lt;br /&gt;
|Conditions||1. Nice GUI for creating simple conditions &amp;lt;br/&amp;gt;2. GUI well documented and understood by support team||1. Only supports simple comparisons and does not AND/OR conditions well &amp;lt;br/&amp;gt;2. Cascading conditions work erratically &amp;lt;br/&amp;gt;3. Slow - database intensive, so can slow down long surveys &amp;lt;br/&amp;gt;4. Some reported problems with re-loading conditions &amp;lt;br/&amp;gt;5. GUI doesn&#039;t scale well when there are dozens, hundreds, or thousands of questions &amp;lt;br/&amp;gt;6. May be slow to convert paper-based surveys since must use SGQA names &amp;lt;br/&amp;gt;7. Often need a programmer to custom-code logic needed for complex branching&lt;br /&gt;
|-&lt;br /&gt;
|Relevance||1. Supports very complex logic, including 80+ functions and math/string operators &amp;lt;br/&amp;gt;2. Perfect support for cascading logic &amp;lt;br/&amp;gt;3. Fast - no extra database calls, so supports 1000+ question surveys &amp;lt;br/&amp;gt;4. No problems with re-loading logic since does not require SGQA codes &amp;lt;br/&amp;gt;5. Syntax-highlighting scales to 1000+ question surveys &amp;lt;br/&amp;gt;6. Easy and fast to use for groups wanting to computerize existing paper-based suveys.  &amp;lt;br/&amp;gt;7. Easily supports semi-structured interviews and epidemiological surveys without needing a programmers||1. No GUI for simple conditions - use syntax-highlighting instead &amp;lt;br/&amp;gt;2. New, so support teams have not mastered EM yet.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:67--&amp;gt;&lt;br /&gt;
The bottom is that if you are happy with how LimeSurvey 1.91+ works, there is no reason to change what you do.&lt;br /&gt;
&lt;br /&gt;
==What are some other benefits of using EM?== &amp;lt;!--T:68--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:69--&amp;gt;&lt;br /&gt;
Here are some of the other reasons you might want to use EM.&lt;br /&gt;
#Calculations - you can create any calculation you can think of:&lt;br /&gt;
#*You have access to all common mathematical operators and functions&lt;br /&gt;
#*You have access to 70+ mathematical, date, and string processing functions&lt;br /&gt;
#*It is fairly easy for developers to add new functions if users need them&lt;br /&gt;
#Storing Calculations to Database&lt;br /&gt;
#*You can now compute simple and complex calculations and/or scale scores AND have them stored in the database without needing JavaScript.&lt;br /&gt;
#*You use the Equation question type to accomplish this.&lt;br /&gt;
#Assessments&lt;br /&gt;
#*You can now create assessments or scale scores from any question type, not just the subset that used to be supported&lt;br /&gt;
#*You can use Tailoring to show running or total assessment scores anywhere needed - even on the same page&lt;br /&gt;
#*You have more control over the reports generated based upon those assessment scores&lt;br /&gt;
#*You can store assessment scores in the database without needing JavaScript&lt;br /&gt;
#*You can hide assessment scores without needing JavaScript or CSS&lt;br /&gt;
#Replacement Fields&lt;br /&gt;
#*Instead of using {INSERTANS:SGQA}, you can just use the Question Code - this makes it easier to read and validate.&lt;br /&gt;
#*This also avoids the common need to edit questions to change the SGQA code to make everything work.&lt;br /&gt;
#Tailoring - you can conditionally display text based upon other values&lt;br /&gt;
#*Use the appropriate title for a subject, like (e.g. &amp;quot;Hello &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;Mr./Mrs.] Smith&amp;quot;)&lt;br /&gt;
#*Output gramatically correct sentences based when singular/plural matter:  (e.g. &amp;quot;You have 1 child&amp;quot; vs. &amp;quot;You have 2 children&amp;quot;)&lt;br /&gt;
#*Appropriately conjugate verbs and decline nouns based upon subject&#039;s gender and plurality.&lt;br /&gt;
#New Variable Attributes - you can access the following to do your tailoring:&lt;br /&gt;
#* (no suffix) -  an alias for qcode.code&lt;br /&gt;
#*.code - the selected response code for the question if it is relevant (otherwise blank), or the text value if it is not a coded question&lt;br /&gt;
#*.NAOK - same as .code, but can be part of calculations or lists even if irrelevant&lt;br /&gt;
#*.value - the assessment value for the question if it is relevant (otherwise blank), or the text value if it is not a coded question&lt;br /&gt;
#*.valueNAOK - same as .value, but can be part of calculations or lists even if irrelevant&lt;br /&gt;
#*.shown - the answer as displayed to the user (this is what {INSERTANS:xxx}  does)&lt;br /&gt;
#*.qid - the question ID&lt;br /&gt;
#*.gid - the group ID&lt;br /&gt;
#*.sgqa - the SGQA value for the question&lt;br /&gt;
#*.jsName - the correct javascript variable name for the question, regardless whether defined on this page or another&lt;br /&gt;
#*.qseq - the question sequence (starting from 0)&lt;br /&gt;
#*.gseq - the group sequence (starting from 0)&lt;br /&gt;
#*.mandatory - whether the question is mandatory (Y/N)&lt;br /&gt;
#*.question - the text of the question&lt;br /&gt;
#*.relevance - the relevance equation for the question&lt;br /&gt;
#*.grelevance - the relevance equation for the group&lt;br /&gt;
#*.relevanceStatus - whether or not the question is currently relevant (1 if true, 0 if false)&lt;br /&gt;
#*.type - the question type (the one character code)&lt;br /&gt;
#Dynamic On-Page Changes&lt;br /&gt;
#*All Relevance, Calculation, and Tailoring works dynamically on a page - so changes in values instantly update the page&lt;br /&gt;
#*So, you have questions dynamically appear/disappear based upon whether they are relevant&lt;br /&gt;
#*Questions are also dynamically tailored based upon responses on the page, so you can see running totals, tailored sentences and customized reports.&lt;br /&gt;
#New Data Entry Screen&lt;br /&gt;
#*In addition to using the current data-entry system, you can just use Survey-All-In-One.&lt;br /&gt;
#*This supports the on-page relevance and tailoring, so data entry clerks can quickly tab through and they will only have to enter the relevant responses&lt;br /&gt;
#*This can be critical if your data entry person needs to see the tailoring, which is also dynamic.&lt;br /&gt;
#Eliminates the need for most custom JavaScript&lt;br /&gt;
#*EM easily supports complicated computations, scoring, tailoring and conditional logic.&lt;br /&gt;
#*Some things will still need JavaScript (like custom layouts and conditionally hiding question sub-elements), but your JavaScript can use the EM functions so that you can access questions by their Qcode instead of SGQA, and access any of the question properties listed above.&lt;br /&gt;
&lt;br /&gt;
==What are some other helpful new features enabled by EM?== &amp;lt;!--T:70--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:71--&amp;gt;&lt;br /&gt;
Regardless of whether you continue to use the Conditions Editor or manually compose Relevance Equations, you get these additional benefits:&lt;br /&gt;
#You can create more complex validation criteria&lt;br /&gt;
#*All of the advanced question attribute (like max_answers, min_num_value_n, max_num_value) can use Expressions.  So, you min/max criteria can be easily adjusted based upon prior responses, even if they are on the same page.&lt;br /&gt;
#*EM also handles all regular-expression-based validation, so you can robustly combine preg and equation-based question attributes.&lt;br /&gt;
#Easy Re-ordering (or deleting) of Questions and Groups&lt;br /&gt;
#*Prior to version 1.92, you could not re-order questions or groups if LimeSurvey thought that such-re-ordering could break conditions in which they were used.  Similarly, you could not delete questions if any other questions depended upon them.&lt;br /&gt;
#*With EM&#039;s syntax highlighting, it is easy to see and validate whether you try to use questions before they are declared.  So, we now let you re-order or delete questions and groups whenever you like.  EM will update all of the syntax highlighting to show you potential errors.&lt;br /&gt;
#*The re-order questions view has been enhanced to help with such review.  It now shows the question&#039;s relevance equation and tailoring, so you can immediately see whether any variables become pink (meaning they are used before being declared).&lt;br /&gt;
#The Question/Group Navigation Index is always available and accurate&lt;br /&gt;
#*Prior to version 1.92, these indexes were not available if there were complex conditions&lt;br /&gt;
#*With EM, we can guarantee that they are accurate.&lt;br /&gt;
#*Subjects can even jump back, to a prior question, change the answer, then jump forward (or submit)&lt;br /&gt;
#**When jumping forwards, EM will re-validate all of the intervening questions/groups.&lt;br /&gt;
#**If any questions become irrelevant, they will be NULLed in the database so that your data is internally consistent&lt;br /&gt;
#**If any questions become relevant or newly fail mandatory or validation rules, EM will stop on that page and force the user to answer those questions before jumping to their final destination.&lt;br /&gt;
#Auto-conversion of Conditions to Relevance&lt;br /&gt;
#*When you upgrade your database, all existing surveys that have conditions will have relevance equations generated for them&lt;br /&gt;
#*Whenever you import a survey, relevance equations will be created as needed&lt;br /&gt;
#*Whenever you add, delete, or modify conditions, EM will generate the appropriate relevance equation.&lt;br /&gt;
#Convenient Syntax Highlighting&lt;br /&gt;
#*When EM shows the relevance equation, it will show the Qcode, even if you entered an SGQA code, as we assume this will be easier to read.&lt;br /&gt;
#*All variables are color coded to show whether they were declared before or after the current question (or before or after the current group).  This lets you quickly detect and fix cases where you try to use variables for relevance (including array_filter), tailoring, or validation equations prior to declaring them.&lt;br /&gt;
#*In addition, if you hover your mouse over the color-coded variable, you will see the most important metadata about that question.   This includes the Group Sequence #, Question Sequence #, Qcode, Text of the question, and all available answer choices (if it is a question type with enumerated answer choices).&lt;br /&gt;
#**The list of answer choices uses this syntax:  &#039;answers&#039;:{key:val, ... }.&lt;br /&gt;
#**&#039;&#039;key&#039;&#039; has the syntax &#039;&#039;&#039;&#039;scale~code&#039;&#039;&#039;&#039; where &#039;&#039;scale&#039;&#039; is the answer scale (e.g. for dual scale), and &#039;&#039;code&#039;&#039; is the answer code.&lt;br /&gt;
#**&#039;&#039;val&#039;&#039; has the syntax &#039;&#039;&#039;&#039;value~shown&#039;&#039;&#039;&#039; where &#039;&#039;value&#039;&#039; is the assessment value (if using assessments, otherwise &#039;&#039;code&#039;&#039;)(e.g. Qcode.value), and &#039;&#039;shown&#039;&#039; is the display value as seen by the subject (e.g. Qcode.shown)&lt;br /&gt;
#**This means that many surveys can use calculations without needing assessment mode.  If you have enumerated answer options  that are unique, non-decimal, and non-negative, you can simply do calculations on the Qcode.code values.&lt;br /&gt;
#Easy review of entire survey logic and content&lt;br /&gt;
#*There is a new Show Survey Logic feature that lets you see everything about the survey (or group or question) on a single page.&lt;br /&gt;
#*It shows the Group, Question, Sub-Question, and Answer-level details for the selected scope (survey vs. group vs. question)&lt;br /&gt;
#*It also shows the relevance, sub-question-level relevance (for array_filter and array_filter_exclude), and generated validation equation (for preg and any validation rules like min/max sum/number of values), and all non-blank question attributes.&lt;br /&gt;
#*Everything is syntax-highlighted so that you can see potential syntax errors (like unbalanced parentheses or use of variables before they were declared)&lt;br /&gt;
#*The syntax-highligting supports rapid navigation and editing of the survey.&lt;br /&gt;
#**If you click on a variable name, it opens a browser window (or tab) that shows you that question and lets you edit it.&lt;br /&gt;
#**If you click on a group name, it opens a browser window (or tab) showing the group-reorder view so that you can easily move questions around.&lt;br /&gt;
#**All of the question attributes are also syntax highlighted.  This lets you set and see expressions within advanced question options (like basing the max/min number/sum of values on an expression)&lt;br /&gt;
#*The EM author used similar view (a little cleaner) to let his collaborating Epidemiologists and Institutional Review Board validate and authorize surveys with thousands of questions in highly branched and tailored structured interviews&lt;br /&gt;
&lt;br /&gt;
==How Backwards Compatible is EM with 1.91+?== &amp;lt;!--T:72--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:73--&amp;gt;&lt;br /&gt;
LimeSurvey 1.92 is fully backwards-compatible with 1.91+ with one exception/caveat:  1.92 handles less-than / greater-than comparisons against empty values differently than 1.91+.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:74--&amp;gt;&lt;br /&gt;
One of the LimeSurvey demo surveys uses a set of conditions that translates to this relevance equation:  {(age &amp;lt; 16) or (age == 20) or ... or (age == 80)}. In LimeSurvey 1.91+, (age &amp;lt; 16) is FALSE when there is no answer (the value is blank).  However, in LimeSurey 1.92, (age &amp;lt; 16) is TRUE when there is no answer, since both PHP and JavaScript treat blank as 0 in mathematical comparisons.  Thus, 1.91+ would hide that question when age was unanswered, but 1.92 would show it.  We went to great pains to prevent this, but since we needed to have the Expressions generate identical results in PHP and JavaScript, there was no way to make 1.92 treat &amp;quot;&amp;quot; &amp;lt; 16 as FALSE.  Fortunately, there is an easy work-around for this.  If you want (age &amp;lt; 16) to be FALSE, then use this expression instead: {(!is_empty(age) and age &amp;lt; 16)}.  You can use the new [[Show Logic File|Survey Logic File]] view to quickly identify and fix any such comparisons in your survey.&lt;br /&gt;
&lt;br /&gt;
=Getting Started= &amp;lt;!--T:75--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:76--&amp;gt;&lt;br /&gt;
The best way to get started with EM is to:&lt;br /&gt;
*Install the latest stable version from http://www.limesurvey.org/en/download &lt;br /&gt;
*Import and explore the [[Expression Manager Sample Surveys|sample surveys]].&lt;br /&gt;
*Explore the [[Expression Manager HowTos|use cases and HowTos]] and [[Expression Manager Examples|step-by-step examples]].&lt;br /&gt;
*Explore the EM documentation (this page)&lt;br /&gt;
*Examine the built-in EM test suite&lt;br /&gt;
**From any survey, under tools, select the EM option&lt;br /&gt;
**Available Functions lists the 70+ functions and syntax&lt;br /&gt;
**Unit Tests of Isolated Expressions&lt;br /&gt;
***shows examples of using all EM functions and operators, and the PHP and JavaScript results&lt;br /&gt;
***note there are few functions that generate different results in the PHP and JavaScript versions, so this page lets you plan your EM logic accordingly.&lt;br /&gt;
&lt;br /&gt;
=What Functionality does Expression Manager Extend/Replace? (LimeSurvey &amp;lt;= 1.91+)= &amp;lt;!--T:77--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Conditions =&amp;gt; Relevance== &amp;lt;!--T:78--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:79--&amp;gt;&lt;br /&gt;
Conditions controlled which  questions are visible.  The general syntax was &#039;&#039;SGQA operator Value&#039;&#039;, like &#039;&#039;111X2X3 == &amp;quot;Y&amp;quot;&#039;&#039;.  Conditions could be ANDed or ORed together, but mixing ANDs and ORs was difficult.  The conditions themselves were stored in a separate table, and large portion of LimeSurvey&#039;s code was devoted to managing Conditions.  Because of extensive database access, processing large numbers of conditions could cause noticable performance problems.  Furthermore, once you had conditions assigned to questions or groups, you were often not allowed to re-order or delete them.&lt;br /&gt;
&lt;br /&gt;
==Assessments =&amp;gt; Equations and  Micro-Tailoring== &amp;lt;!--T:80--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:81--&amp;gt;&lt;br /&gt;
Assessments let users create scale scores from a collection of questions.  However, they could not dynamically change on the current page, and their values were not stored to the database.&lt;br /&gt;
&lt;br /&gt;
==Replacements =&amp;gt; Micro-Tailoring== &amp;lt;!--T:82--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:83--&amp;gt;&lt;br /&gt;
Users could tailor some messages and questions based  upon prior responses.  For example, a question might be, &#039;&#039;{TOKEN:FIRSTNAME}, you said {INSERTANS:111X3X4} was your favorite sport&#039;&#039;.  However, it was not possible to do conditional tailoring (like say &amp;quot;Mr.&amp;quot; or &amp;quot;Mrs.&amp;quot; depending upon the person&#039;s gender), or conjugate verbs or decline nouns without fancy JavaScript.  Authors could implement surveys that seemed to tailor questions, but it required separate questions for each permutation, and complex conditions to decide which questions to display.&lt;br /&gt;
&lt;br /&gt;
==Validation== &amp;lt;!--T:84--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:85--&amp;gt;&lt;br /&gt;
Question could be validated with Regular expressions, or minimum/maximum values, or let an SGQA response serve as the minimum or maximum value.  However, validations could not be based upon calculations of other variables without fancy JavaScript.&lt;br /&gt;
&lt;br /&gt;
==Equations== &amp;lt;!--T:86--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:87--&amp;gt;&lt;br /&gt;
Equations were not supported without fancy JavaScript.&lt;br /&gt;
&lt;br /&gt;
==Equation Question Type== &amp;lt;!--T:88--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:89--&amp;gt;&lt;br /&gt;
Equations could not be saved to the database (e.g. the final score for an assessment) without fancy JavaScript.&lt;br /&gt;
&lt;br /&gt;
=How Will Expression Manager Replace/Extend That Functionality?= &amp;lt;!--T:90--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:91--&amp;gt;&lt;br /&gt;
The Expression Manager is a new core module within LimeSurvey that makes it much easier to support the type of complex functionality that used to require custom JavaScript.  It is also replacing the way LimeSurvey currently manages Conditions and Assessments.&lt;br /&gt;
&lt;br /&gt;
==New Terminology When Referring to Expression Manager (EM)== &amp;lt;!--T:92--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:93--&amp;gt;&lt;br /&gt;
EM &amp;quot;thinks&amp;quot; of its functionality in the following terms:&lt;br /&gt;
*&#039;&#039;&#039;Relevance-based Branching&#039;&#039;&#039; - if a question is relevant, then ask it, otherwise don&#039;t (e.g. make it invisible, and mark it as NULL in the database).  There is a new Relevance field for all Question types, and also for each Group (so you can apply a set of conditions to an entire group without having to copy the same condition to each question, and/or combine group and question-level conditional logic).&lt;br /&gt;
*&#039;&#039;&#039;Tailoring&#039;&#039;&#039; - Once you know which questions should be asked, tailoring (sometimes called &#039;&#039;piping&#039;&#039;) specifies how the question should be asked. This lets you support not only simple subsitution (like {TOKEN:FIRSTNAME}), but also conjugation of verbs and declination of nouns based upon the gender or number of your subjects.  It also lets you change the message you deliver to a subject based upon whether they answered (or how they answered) other questions.&lt;br /&gt;
*&#039;&#039;&#039;Equations&#039;&#039;&#039; - EM adds a new question type called Equation which stores the result of an Expression.  These equations results are computed and written to the database, even if you hide them on the page.  Thus, they are useful for hidden scoring calculations, navigation based upon complex equations, assessments, and reports that should be generated and easily available within the database.&lt;br /&gt;
&lt;br /&gt;
===Relevance and Cascading Relevance=== &amp;lt;!--T:94--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:95--&amp;gt;&lt;br /&gt;
Every question type now has a Relevance option which controls whether the question is displayed.  EM processes each of the Relevance Equations in the order they should appear in the survey.  If the expression is true (or missing - to support legacy surveys), the question will be displayed. If it is not relevant, then the question will be hidden, and the value will be NULLed in the database.  If there are no relevant questions in a group, the entire group will be skipped.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:96--&amp;gt;&lt;br /&gt;
Moreover, if any of the variables within an expression is irrelevant, then the expression always evaluates to false.  This enables Cascading Relevance so that you do not have to write very long Relevance equations for each question.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:97--&amp;gt;&lt;br /&gt;
Say you have 5 questions Q1-Q5, and you only want to show Q2 if Q1 was answered, and Q3 if Q2 was answered, etc.  The relevance equations might be:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:98--&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Question Code!!Relevance!!Question&lt;br /&gt;
|-&lt;br /&gt;
|Q1||1||What is your name?&lt;br /&gt;
|-&lt;br /&gt;
|Q2||Q1||{Q1}, how old are you?&lt;br /&gt;
|-&lt;br /&gt;
|Q3||Q2||So, you are {Q2} years old.  Are you married?&lt;br /&gt;
|-&lt;br /&gt;
|Q4||Q3 == &amp;quot;Y&amp;quot;||{Q1}, how long have you been married?&lt;br /&gt;
|-&lt;br /&gt;
|Q5||Q4||How many children do you have, {Q1}?&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:99--&amp;gt;&lt;br /&gt;
The relevance calculations also work in JavaScript - so you could put all the above questions on one page and it would still work as expected.  In fact, EM totally replaces how EM processes Survey vs. Group vs. Question-at-a-time survey formats.  They now all use the exactly same navigation engine so they work identically regardless of survey style.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:100--&amp;gt;&lt;br /&gt;
As long as you are on the same page, any data you entered will still be there, just hidden.  So, if you enter some information, then choose an option that makes them irrelevant, then make them relevant again, your answers will still be available.  However, as soon as you move to a different page, all irrelevant responses will be lost to integrity of the dataset.&lt;br /&gt;
&lt;br /&gt;
===Group-Level Relevance=== &amp;lt;!--T:101--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:102--&amp;gt;&lt;br /&gt;
Expression Manager also supports group-level relevance.  This makes it easier to implement looping.   Say you want to collect information about up to 10 entities (such a products or people in a household), where you first determine how many entities need follow-up (such as by asking how many people live in a household, or having people check which products they like from a long list).  After knowning how many entities need follow-up, you can use Group-level relevance like {count &amp;gt;= 1}, {count &amp;gt;=2}, ... {count &amp;gt;= 10} for each of the 10 groups of follow-up questions.  Within each group, you can have question-level conditional logic (e.g. gender or age-specific follow-up questions for each subject).  The question and group-level relevance equations are ANDed together to determine which should be shown.&lt;br /&gt;
&lt;br /&gt;
===Tailoring / Piping=== &amp;lt;!--T:103--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:104--&amp;gt;&lt;br /&gt;
Anything within curly braces is now treated as an Expression (with one exception described below).  Expressions have acccess to all of the LimeReplacementFields, all of the variables (via several aliases), all typical equation operators (mathematical, logical, and comparison), and dozens of functions (that even work dynamically on the client-side).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:105--&amp;gt;&lt;br /&gt;
Using these equations, you can do things such as:&lt;br /&gt;
#Conditionally show tailored messages to the respondants based upon prior responses&lt;br /&gt;
#Create Assessments and show Assessment results (or conditionally branch or show messages) based upon those results, all without using the Assessments module itself&lt;br /&gt;
#Conjugate verbs and decline nouns within questions, answers, and reports.&lt;br /&gt;
#Show summaries of responses before the &amp;quot;Show your answers&amp;quot; page at the end of the survey&lt;br /&gt;
&lt;br /&gt;
===Equations=== &amp;lt;!--T:106--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:107--&amp;gt;&lt;br /&gt;
There is a new question type called  Equation.  It is like a Boilerplate questions, except that it stores the value of what is displayed in the database.  So, if the Equation Question text contains an Assessment computation, that value would be stored in the database in a variable that can be displayed within public or private statistics.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:108--&amp;gt;&lt;br /&gt;
This solves a common request for storing Assessment scores within the database&lt;br /&gt;
&lt;br /&gt;
==Syntax== &amp;lt;!--T:109--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:110--&amp;gt;&lt;br /&gt;
Anything contained within curly braces is now considered an Expression (with one exception:  there must be no leading or trailing whitespace - this is needed to ensure the Expression Manager does not try to process embedded JavaScript).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:111--&amp;gt;&lt;br /&gt;
Note, it is OK for expressions to span multiple lines, as long as there is no whitespace after the opening  curly brace or before the closing curly brace.  This is especially helpful for nested if() statements like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:112--&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;{if(is_empty(PFTotals),&lt;br /&gt;
 &#039;&#039;,&lt;br /&gt;
 if(PFTotals &amp;gt;= -5 &amp;amp;&amp;amp; PFTotals &amp;lt;= -4,&lt;br /&gt;
   &#039;Very Soft&#039;,&lt;br /&gt;
   if(PFTotals &amp;gt;= -3 &amp;amp;&amp;amp; PFTotals &amp;lt;= -2,&lt;br /&gt;
     &#039;Soft&#039;,&lt;br /&gt;
     if(PFTotals == -1,&lt;br /&gt;
       &#039;Somewhat Soft&#039;,&lt;br /&gt;
       if(PFTotals == 0,&lt;br /&gt;
         &#039;Moderate&#039;,&lt;br /&gt;
         if(PFTotals == 1,&lt;br /&gt;
           &#039;Somewhat Hard&#039;,&lt;br /&gt;
           if(PFTotals &amp;gt;= 2 &amp;amp;&amp;amp; PFTotals &amp;lt;= 3,&lt;br /&gt;
             &#039;Hard&#039;,&lt;br /&gt;
             if(PFTotals &amp;gt;= 4 &amp;amp;&amp;amp; PFTotals &amp;lt;= 5,&lt;br /&gt;
               &#039;Very Hard&#039;,&lt;br /&gt;
               &#039;&#039;&lt;br /&gt;
             )&lt;br /&gt;
           )&lt;br /&gt;
         )&lt;br /&gt;
       )&lt;br /&gt;
     )&lt;br /&gt;
   )&lt;br /&gt;
 )&lt;br /&gt;
)}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:138--&amp;gt;&lt;br /&gt;
&amp;lt;div id=&amp;quot;EMsyntax&amp;quot;&amp;gt;Expression Manager supports the following syntax:&amp;lt;/div&amp;gt;&lt;br /&gt;
*All standard mathematical operators (e.g. +,-,*,/,!)&lt;br /&gt;
*All standard comparison operators (e.g. &amp;lt;,&amp;lt;=,==,!=,&amp;gt;,&amp;gt;=, plus these equivalents:  lt,le,eq,ne,gt,ge)&lt;br /&gt;
*Parentheses (so you can group sub-expressions)&lt;br /&gt;
*Conditional operators (e.g. &amp;amp;&amp;amp;,| | and these equivalents: and,or)&lt;br /&gt;
*Single and double-quoted strings (which can each embed strings with the other quote type)&lt;br /&gt;
*Comma operator (so can have a list of expressions and just return the final result)&lt;br /&gt;
*Assignment operator (=)&lt;br /&gt;
*Pre-defined variables (to refer to questions, question attributes, and responses) - e.g. all of the SGQA codes&lt;br /&gt;
*Pre-defined functions (there are already 70+, and it is easy to add more)&lt;br /&gt;
&lt;br /&gt;
=== Operators === &amp;lt;!--T:211--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:139--&amp;gt;&lt;br /&gt;
EM syntax follows normal operator precedence:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:140--&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Level!!Operator(s)!!Description&lt;br /&gt;
|-&lt;br /&gt;
|1||()||parentheses for grouping or calling functions&lt;br /&gt;
|-&lt;br /&gt;
|2||! - +||unary operators: not, negation, unary-plus&lt;br /&gt;
|-&lt;br /&gt;
|3||* /||times, divide&lt;br /&gt;
|-&lt;br /&gt;
|4||+ -||plus, minus&lt;br /&gt;
|-&lt;br /&gt;
|5||&amp;lt; &amp;lt;= &amp;gt; &amp;gt;= lt le gt ge||relative comparisons&lt;br /&gt;
|-&lt;br /&gt;
|6||== != eq ne||equality comparisons&lt;br /&gt;
|-&lt;br /&gt;
|7||and||logical AND&lt;br /&gt;
|-&lt;br /&gt;
|8||or||logical OR&lt;br /&gt;
|-&lt;br /&gt;
|9||=||assignment operator&lt;br /&gt;
|-&lt;br /&gt;
|10||,||comma operator&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:141--&amp;gt;&lt;br /&gt;
Note, for consistency between JavaScript and PHP, the plus operator (+) does addition if both operands are numeric, but does concatenation if both parts are non-numeric strings.  However, we recommend using the join() function for concatenation, as that makes your intent more clear, and avoids unexpected results if you were expecting strings but got numbers instead (or vice versa).&lt;br /&gt;
&lt;br /&gt;
===Caution about using Assignment Operator (=)=== &amp;lt;!--T:142--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:143--&amp;gt;&lt;br /&gt;
Note, you should avoid using the assignment operators unless absolutely necessary, since they may cause unexpected side-effects.  For example, if you change the value of a previous response, the cascading relevance and validation logic between that question and the current question is not re-computed, so you could end up with internally inconsistent data (e.g. questions that stay answered but should have been NULLed, or questions that are skipped but should have been answered).  In general, if you want to assign a value to a variable, you should create an Equation question type, and use an expression to set its value.  However, there are some rare times that people really need this operator, so we made it available.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:144--&amp;gt;&lt;br /&gt;
To help caution you about this operator, it is shown in red font within the syntax equations (so that you don&#039;t confuse it with &amp;quot;==&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
===Using Assignment Operator=== &amp;lt;!--T:145--&amp;gt;&lt;br /&gt;
The main reasons you may want to use assignment are:&lt;br /&gt;
*You need to set the default value for a question that does not accept defaults via equation (such as list radio, where the user interface lets you pick one of the answer options, but does not let you enter an equation).  However, be careful, as LimeSurvey will not be able to validate that your equation generates one of the allowable answers for that question.&lt;br /&gt;
*You need to forcibly change the response to a previous question based upon a later response&lt;br /&gt;
* etc...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:212--&amp;gt;&lt;br /&gt;
You can use all expression manager system for this purpose. It&#039;s better to use an [[Question_type_-_Equation|Equation question]] type to this purpose.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:213--&amp;gt;&lt;br /&gt;
Some example:&lt;br /&gt;
* Set answer to a short text question in lowercase : &amp;lt;code&amp;gt;{QCODE=strtolower(QCODE.NAOK)}&amp;lt;/code&amp;gt;&lt;br /&gt;
* Set a default answer to an array question type at start of a survey : &amp;lt;code&amp;gt;{Q1_SQ1=(is_empty(Q1_SQ1.NAOK),&amp;quot;A99&amp;quot;,Q1_SQ1.NAOK)}&amp;lt;/code&amp;gt;&lt;br /&gt;
* Set a default answer to an array texts question type at start of a survey : &amp;lt;code&amp;gt;{Q1_SQY1_SQX1 = (is_empty(Q1_SQY1_SQX1.NAOK),&amp;quot;Inserted answer&amp;quot;, Q1_SQY1_SQX1.NAOK)}&amp;lt;/code&amp;gt;&lt;br /&gt;
* Set an answer with condition : &amp;lt;code&amp;gt;{QCODE=if(YesNo=&amp;quot;Y&amp;quot;,&amp;quot;A1&amp;quot;,&amp;quot;&amp;quot;)}&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== XSS security == &amp;lt;!--T:214--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:215--&amp;gt;&lt;br /&gt;
With XSS enable, some expression manager system can not be used : &lt;br /&gt;
* starting a HTML tag in expression but ending in another expression&lt;br /&gt;
* use a complex expression in URL. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:216--&amp;gt;&lt;br /&gt;
Example and workaround&lt;br /&gt;
* &amp;lt;code&amp;gt;{if( 1 ,&amp;quot;&amp;amp;lt;strong&amp;amp;gt;&amp;quot;,&amp;quot;&amp;quot;)}information{if( 1 ,&amp;quot;&amp;amp;lt;/strong&amp;amp;gt;&amp;quot;,&amp;quot;&amp;quot;)}&amp;lt;/code&amp;gt; is broken with XSS security, here you can use &amp;lt;code&amp;gt;{if(1,&amp;quot;&amp;lt;strong&amp;amp;gt;information&amp;amp;lt;/strong&amp;amp;gt;&amp;quot;,&amp;quot;information&amp;quot;)}&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;&amp;amp;lt;a href=&amp;quot;/script.php?value={if(QCODE == &amp;quot;Y&amp;quot;,&amp;quot;yes&amp;quot;,&amp;quot;no&amp;quot;)}&amp;quot;&amp;amp;gt;next&amp;amp;lt;/a&amp;amp;gt;&amp;lt;/code&amp;gt;, here you can use an equation question because using a complete question code is OK : &amp;lt;code&amp;gt;&amp;amp;lt;a href=&amp;quot;/script.php?value={EQUATION.NAOK}&amp;quot;&amp;amp;gt;next&amp;amp;lt;/a&amp;amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Access to Variables== &amp;lt;!--T:146--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:147--&amp;gt;&lt;br /&gt;
Expression Manager provides read-only access to whichever variables we might need.  For backwards compatibility, it provides access to the following:&lt;br /&gt;
*TOKEN:xxx - the value of a TOKEN (e.g. TOKEN:FIRSTNAME, TOKEN:ATTRIBUTE_5) (Only for NOT anonymous survey).&lt;br /&gt;
*[[Adding a question#Information_from_previous_answers|INSERTANS:SGQA]] - the display value of an answer (e.g. &amp;quot;Yes&amp;quot;). For Expression Manager it&#039;s the same that using {QCODE.shown}.&lt;br /&gt;
*All [[The_template_editor#Keywords|{XXX} values used by templates]].&lt;br /&gt;
*In question text, you can use {QID} replaced by the question id and {SGQ} replaced by the SGQA of the question&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:148--&amp;gt;&lt;br /&gt;
In addition, Expression Manager lets you refer to variables by the Question Code (the &#039;title&#039; column in the questions table within the database).  This is also the variable label used when you export your data to SPSS, R, or SAS.  For example, if you have questions about name, age, and gender, you could call those variables &#039;&#039;name&#039;&#039;, &#039;&#039;age&#039;&#039;, and &#039;&#039;gender&#039;&#039; instead of &#039;&#039;12345X13X22&#039;&#039;, &#039;&#039;12345X13X23&#039;&#039;, and  &#039;&#039;12345X13X24&#039;&#039;.  This makes equations easier for everyone to read and validate the logic, plus makes it possible to shuffle questions around without having to keep track of group or question numbers.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:210--&amp;gt;&lt;br /&gt;
&amp;lt;div class=&#039;simplebox&#039;&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Important:&#039;&#039;&#039; It is only safe to refer to variables that occur in preceding pages or questions.&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:149--&amp;gt;&lt;br /&gt;
Furthermore, Expression Manager lets you access many properties of the Question:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:150--&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Syntax!!Meaning!!Example!!Example Result&lt;br /&gt;
|-&lt;br /&gt;
|Qcode||an alias for Qcode.code||{implode(&#039;,&#039;,name,gender)}||&#039;Tom&#039;,&#039;M&#039;&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.code||the selected response code for the question if it is relevant (otherwise blank), or the text value if it is not a coded question||{implode(&#039;,&#039;,name.code,gender.code)}||&#039;Tom&#039;,&#039;M&#039;&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.NAOK||same as Qcode - see discussion of NAOK||{gender.NAOK}||&#039;M&#039;&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.value||the assessment value for the question if it is relevant (otherwise blank), or the text value if it is not a coded question||{gender.value}||&#039;1&#039;&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.valueNAOK||same as Qcode.value - see discussion about NAOK||{gender.valueNAOK}||&#039;1&#039;&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.shown||the dispay value for the question||{implode(&#039;,&#039;,name.shown,gender.shown)}||&#039;Tom&#039;,&#039;Male&#039;&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.question||the text of the question||{gender.question}||&#039;What is your gender?&#039;&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.mandatory||whether the question is mandatory (Y/N)||{gender.mandatory}||&#039;N&#039;&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.qid||the internal question number (not the sequential number)||{gender.qid}||337&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.type||the question type||{gender.type}||&#039;G&#039;&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.jsName||the correct javascript name for the question, regardless whether declared on or off this page||{gender.jsName}||&#039;java1827X3X337&#039;&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.gid||the internal group number (not the sequential number)||{gender.gid}||3&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.qseq||the sequential number of the question, starting from 0||{gender.qseq}||5&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.gseq||the sequential number of the group, starting from 0||{gender.gseq}||1&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.relevanceStatus||whether the question is currently relevant (0 or 1)||{gender.relevanceStatus}||1&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.relevance||the question-level relevance equation||{gender.relevance}||&#039;!is_empty(name)&#039;&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.grelevance||the  group-level relevance equation||{gender.grelevance}||&#039;num_children &amp;gt;= 5&#039;&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.sgqa||the SGQA value for this question||{gender.sgqa}||&#039;1827X3X337&#039;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== HTML editor issue=== &amp;lt;!--T:151--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:217--&amp;gt;&lt;br /&gt;
{{Alert|This issue is fixed after 2.05 build 140803}} &lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:152--&amp;gt;&lt;br /&gt;
If you use HTML editor, some characters are replaced by HTML entities.&lt;br /&gt;
* &amp;amp; by &amp;amp;amp;amp;&lt;br /&gt;
* &amp;lt; by &amp;amp;amp;lt;&lt;br /&gt;
* &amp;gt; by &amp;amp;amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:209--&amp;gt;&lt;br /&gt;
If you use HTML editor you need to use :&lt;br /&gt;
* and for &amp;amp;&lt;br /&gt;
* lt for &amp;lt;&lt;br /&gt;
* le for &amp;lt;=&lt;br /&gt;
* gt for &amp;gt;&lt;br /&gt;
* ge for &amp;gt;=&lt;br /&gt;
&lt;br /&gt;
==Qcode Variable Naming== &amp;lt;!--T:153--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:154--&amp;gt;&lt;br /&gt;
Here are the details of how to construct a Qcode (and access some properties) by question type.  In general, Qcodes are constructed as:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:155--&amp;gt;&lt;br /&gt;
  QuestionCode . &#039;_&#039; . SubQuestionID . &#039;_&#039; . ScaleId&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:208--&amp;gt;&lt;br /&gt;
For comment and other, question code are QuestionCode_comment and QuestionCode_other&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:156--&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Type!!Description!!Code!!SubQs!!Answer Options!!Scales!!Answer Code!!Answer Shown!!Relevance&lt;br /&gt;
|-&lt;br /&gt;
|5||5 Point Choice Radio-Buttons||Q1|| ||1-5|| ||{Q1}||{Q1.shown}||{Q1==3}&lt;br /&gt;
|-&lt;br /&gt;
|B||Array (10 Point Choice) Radio-Buttons||Q2||L1-L6||1-10|| ||{Q2_L2}||{Q2_L2.shown}||{Q2_L2==7}&lt;br /&gt;
|-&lt;br /&gt;
|A||Array (5 Point Choice) Radio-Buttons||Q3||1-5||1-5|| ||{Q3_1}||{Q3_1.shown}||{Q3_1&amp;gt;=3}&lt;br /&gt;
|-&lt;br /&gt;
|1||Array (Flexible Labels) Dual Scale||Q4||sq1-sq5||0:a1-a3||1:b1-b3||{Q4_sq1_0}||{Q4_sq1_1.shown}||{Q4_sq1_1==&#039;b2&#039;}&lt;br /&gt;
|-&lt;br /&gt;
|H||Array (Flexible) - Column Format||Q5||1-5||s,m,t|| ||{Q5_1}||{Q5_1.shown}||{Q5_1==&#039;s&#039;}&lt;br /&gt;
|-&lt;br /&gt;
|F||Array (Flexible) - Row Format||Q6||F1-F5||1-5|| ||{Q6_F3}||{Q6_F3.shown}||{Q6_F3==4}&lt;br /&gt;
|-&lt;br /&gt;
|E||Array (Increase/Same/Decrease) Radio-Buttons||Q7||1-7||I,S,D|| ||{Q7_4}||{Q7_4.shown}||{Q7_4==&#039;D&#039;}&lt;br /&gt;
|-&lt;br /&gt;
|:||Array (Multi Flexi) 1 To 10||Q8||ls1,todo,ls2||min,max,avg|| ||{Q8_ls1_max}||{Q8_ls2_avg.shown}||{Q8_ls2_min==7}&lt;br /&gt;
|-&lt;br /&gt;
|;||Array (Multi Flexi) Text||Q9||hp,st,sw||1st,2nd,3rd|| ||{Q9_hp_3rd}||{Q9_hp_3rd.shown}||{Q9_hp_3rd==&#039;Peter&#039;}&lt;br /&gt;
|-&lt;br /&gt;
|C||Array (Yes/Uncertain/No) Radio-Buttons||Q10||1-5||Y,N,U|| ||{Q10_1}||{Q10_1.shown}||{Q10_3==&#039;Y&#039;}&lt;br /&gt;
|-&lt;br /&gt;
|X||Boilerplate Question||Q11|| || || || ||{Q11.shown}||&lt;br /&gt;
|-&lt;br /&gt;
|D||Date||Q12|| || || ||{Q12}||{Q12.shown}||&lt;br /&gt;
|-&lt;br /&gt;
|*||Equation||Q13|| || || ||{Q13}||{Q13.shown}||{Q13&amp;gt;5}&lt;br /&gt;
|-&lt;br /&gt;
|~124~||File Upload (records number of files uploaded)||Q14|| || || ||{Q14}|| ||{Q14&amp;gt;0}&lt;br /&gt;
|-&lt;br /&gt;
|G||Gender Drop-Down List||Q15|| ||M,F|| ||{Q15}||{Q15.shown}||{Q15==&#039;M&#039;}&lt;br /&gt;
|-&lt;br /&gt;
|U||Huge Free Text||Q16|| || || ||{Q16}||{Q16.shown}||{strlen(Q16)&amp;gt;100}&lt;br /&gt;
|-&lt;br /&gt;
|I||Language Question||Q17|| || || ||{Q17}||{Q17.shown}||{Q17==&#039;en&#039;}&lt;br /&gt;
|-&lt;br /&gt;
|!||List - Dropdown||Q18|| ||1-5|| ||{Q18}||{Q18.shown}||{Q18==3}&lt;br /&gt;
|-&lt;br /&gt;
|L||List Drop-Down/Radio-Button List||Q19|| ||A-Z|| ||{Q19}||{Q19.shown}||{Q19==&#039;X&#039;}&lt;br /&gt;
|-&lt;br /&gt;
|O||List With Comment Drop-Down/Radio-Button List + Textarea||Q20|| ||A-F|| ||{Q20},{Q20comment}||{Q20.shown}||{Q20==&#039;B&#039;}&lt;br /&gt;
|-&lt;br /&gt;
|T||Long Free Text||Q21|| || || ||{Q21}||{Q21.shown}||{strstr(Q21,&#039;hello&#039;)&amp;gt;0}&lt;br /&gt;
|-&lt;br /&gt;
|M||Multiple Choice Checkbox||Q22||A-F, other|| || ||{Q22_E}, {Q22_other}||{Q22_E.shown}, {Q22_other}||{Q22_E==&#039;Y&#039;}&lt;br /&gt;
|-&lt;br /&gt;
|P||Multiple Choice With Comments Checkbox + Text||Q23||A-F|| || ||{Q23_D}, {Q23_Dcomment}||{Q23_D.shown}||{!is_empty(Q23)}&lt;br /&gt;
|-&lt;br /&gt;
|K||Multiple Numerical Question||Q24||self,mom,dad|| || ||{Q24_self}||{Q24_self.shown}||{Q24_self&amp;gt;30}&lt;br /&gt;
|-&lt;br /&gt;
|Q||Multiple Short Text||Q25||A-F|| || ||{Q25_B}||{Q25_B.shown}||{substr(Q25_B,1,1)==&#039;Q&#039;}&lt;br /&gt;
|-&lt;br /&gt;
|N||Numerical Question Type||Q26|| || || ||{Q26}||{Q26.shown}||{Q26 &amp;gt; 30}&lt;br /&gt;
|-&lt;br /&gt;
|R||Ranking Style||Q27||1-4|| || ||{Q27_1}||{Q27_1.shown}||{Q27_1==3}&lt;br /&gt;
|-&lt;br /&gt;
|S||Short Free Text||Q28|| || || ||{Q28}||{Q28.shown}||{Q28==&#039;mine&#039;}&lt;br /&gt;
|-&lt;br /&gt;
|Y||Yes/No Radio-Buttons||Q29|| || || ||{Q29}||{Q29.shown}||{Q29==&#039;Y&#039;}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==The reserved &#039;this&#039;, &#039;self&#039;, and &#039;that&#039; variables== &amp;lt;!--T:157--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:158--&amp;gt;&lt;br /&gt;
Quite often, you want to evalute all parts of a question, such as counting how many sub-questions have been answered, or summing the scores.  Other times, you want to process just certain rows or columns of a question (such as getting the row or column sums and storing them in the database).  These reserved variables make that process relatively painless.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:159--&amp;gt;&lt;br /&gt;
The &#039;this&#039; variable is used exclusively within the &amp;quot;Whole question validation equation&amp;quot; and &amp;quot;Sub-question validation equation&amp;quot; advanced question options.  It expands to the variable names of each of the cells within those questions.  So, if you want to make sure that each entry is greater than three, you would set the &amp;quot;Sub-question validation equation&amp;quot; to (this &amp;gt; 3).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:160--&amp;gt;&lt;br /&gt;
The &#039;self&#039; and &#039;that&#039; variable are more powerful, and serve as macros which are expanded prior to processing equations.  The syntax choices are:&lt;br /&gt;
*self&lt;br /&gt;
*self.&#039;&#039;suffix&#039;&#039;&lt;br /&gt;
*self.&#039;&#039;sub-selector&#039;&#039;&lt;br /&gt;
*self.&#039;&#039;sub-selector&#039;&#039;.&#039;&#039;suffix&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:161--&amp;gt;&lt;br /&gt;
&#039;&#039;suffix&#039;&#039; is any of the normal qcode suffixes (e.g. NAOK, value, shown)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:162--&amp;gt;&lt;br /&gt;
&#039;&#039;sub-selector&#039;&#039; is one of:&lt;br /&gt;
*comments - only subquestions that are comments (e.g. from multiple choice with comment and list with comment)&lt;br /&gt;
*nocomments - only subquestions that are not comments&lt;br /&gt;
*sq_X - where X is a row or column identifier.  Only sub-questions matching pattern X are selected. Note that search is done on complete code identifier, then sq_X match and include subquestions nX, X, Xn (e.g. if you use sq_1, subquestions a1, 1a, 1, 11 or 001 was included). Put attention at dual scale question type where subquestions code are QCODE_SQCODE_1 and QCODE_SQCODE_1 and to ranking question type where subquestions code are QCODE_1,QCODE_2 ....&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:163--&amp;gt;&lt;br /&gt;
Examples:&lt;br /&gt;
*Has any part of a question been answered?  {count(self.NAOK)&amp;gt;0}&lt;br /&gt;
*What is the assessment score for this question?  {sum(self.value)}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:164--&amp;gt;&lt;br /&gt;
You can also use these to get row and column totals.  Say you have a array of numbers with rows A-E and columns 1-5.&lt;br /&gt;
*What is the grand total?  {sum(self.NAOK)}&lt;br /&gt;
*What is the total of row B?  {sum(self.sq_B.NAOK)}&lt;br /&gt;
*What is the total of column 3? {sum(self.sq_3.NAOK)}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:165--&amp;gt;&lt;br /&gt;
The &#039;that&#039; variable is like the &#039;self&#039; variable, but lets you refer to other questions.  Its syntax is:&lt;br /&gt;
*that.&#039;&#039;qname&#039;&#039;&lt;br /&gt;
*that.&#039;&#039;qname&#039;&#039;.&#039;&#039;suffix&#039;&#039;&lt;br /&gt;
*that.&#039;&#039;qname&#039;&#039;.&#039;&#039;sub-selector&#039;&#039;&lt;br /&gt;
*that.&#039;&#039;qname&#039;&#039;.&#039;&#039;sub-selector&#039;&#039;.&#039;&#039;suffix&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:166--&amp;gt;&lt;br /&gt;
&#039;&#039;qname&#039;&#039; is the question name without any sub-question extensions.  So, say you create a question &#039;q1&#039;, that is its &#039;&#039;qname&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:167--&amp;gt;&lt;br /&gt;
Examples:&lt;br /&gt;
*Has any part of question q1 been answered?  {count(that.q1.NAOK)&amp;gt;0}&lt;br /&gt;
*What is the assessment score for q2?  {sum(that.q2.NAOK)}&lt;br /&gt;
*What is the grand total of q3? {sum(that.q3.NAOK)}&lt;br /&gt;
*What is the total of row C in q4?  {sum(that.q4.sq_C.NAOK)}&lt;br /&gt;
*What is the total of column 2 in q4? {sum(that.q4.sq_2.NAOK)}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:168--&amp;gt;&lt;br /&gt;
The &#039;self&#039; and &#039;that&#039; variables can be used in any relevance,  validation, or tailoring.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:169--&amp;gt;&lt;br /&gt;
The one caveat is that when you use the [[Show Logic File|Show Logic File]] feature, it will show you the expanded value of &#039;self&#039; and &#039;that&#039;.  This lets you see the actual equation that will be generated so that you (and Expression Manager) can validate that the variables exist.  This may seem confusing since you may see quite lenghty equations.  However, if you edit the question, you will see the original equation using &#039;self&#039; and/or &#039;that&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:170--&amp;gt;&lt;br /&gt;
Also note that you should not use these variables if (a) you want to explicitly name each variable used in an equation, or (b) use variables that do not have sub-questions (e.g. single response questions).  In those cases, prefixing a variable with &#039;that&#039; is overkill, and you run the risk of getting unexpected results.&lt;br /&gt;
&lt;br /&gt;
==Usage of NAOK== &amp;lt;!--T:218--&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:219--&amp;gt;&lt;br /&gt;
NAOK --&amp;gt; &amp;quot;Not Applicable&amp;quot; (NA) is alright (OK)&lt;br /&gt;
&lt;br /&gt;
Using NAOK, means that all or some of the variables are irrelevant (e.g. &amp;quot;Not Applicable&amp;quot; (NA) is alright (OK)). &lt;br /&gt;
&lt;br /&gt;
When you put some variable from question in any equation : if this question (or subquestion) is hidden by condition : this disable all equation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:220--&amp;gt;&lt;br /&gt;
For example : count(Q1_SQ1,Q1_SQ2,Q1_SQ3,Q1_SQ4) give always an empty string if one subquestion of Q1 is filtered.&lt;br /&gt;
To count the number of checked subquestion in such question can be count(Q1_SQ1.NAOK,Q1_SQ2.NAOK,Q1_SQ3.NAOK,Q1_SQ4.NAOK). If the sub question is hidden :Expression manager return an empty string.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:221--&amp;gt;&lt;br /&gt;
Without NAOK : if one question or one subquestion is hidden : Expression Manager return always an empty string, same to return false.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:222--&amp;gt;&lt;br /&gt;
The .shown always use the NAOK system (empty string if hidden) but if you need the code of the answer : it&#039;s always a good idea to add .NAOK after the question code. Except if you need it and know what you do.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:223--&amp;gt;&lt;br /&gt;
Another example and information is provided at [[#Overriding_Cascading_Conditions|Overriding Cascading Conditions]]&lt;br /&gt;
&lt;br /&gt;
==Access to Functions== &amp;lt;!--T:171--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:172--&amp;gt;&lt;br /&gt;
Expression Manager provides access to mathematical, string, and user-defined functions, as shown below.  It has PHP and JavaScript equivalents for these functions so that they work identically on server-side (PHP) and client-side (JavaScript).  It is easy to add new functions.&lt;br /&gt;
&lt;br /&gt;
===Implemented Functions=== &amp;lt;!--T:173--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:174--&amp;gt;&lt;br /&gt;
The following functions are currently available:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:175--&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Function!!Meaning!!Syntax&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.abs.php abs]||Absolute value||number abs(number)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.acos.php acos]||Arc cosine||number acos(number)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.addslashes.php addslashes]||Quote string with slashes||string addslashes(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.asin.php asin]||Arc sine||number asin(number)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.atan.php atan]||Arc tangent||number atan(number)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.atan2.php atan2]||Arc tangent of two variables||number atan2(number, number)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.ceil.php ceil]||Round fractions up||number ceil(number)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.checkdate.php checkdate]||Returns true(1) if it is a valid date in gregorian calendar||bool checkdate(month,day,year)&lt;br /&gt;
|-&lt;br /&gt;
|convert_value||Convert a numerical value using a inputTable and outputTable of numerical values||number convert_value(fValue, iStrict, sTranslateFromList, sTranslateToList)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.cos.php cos]||Cosine||number cos(number)&lt;br /&gt;
|-&lt;br /&gt;
|count||count the number of answered (non-blank)questions in the list||number count(arg1, arg12, ..., argN)&lt;br /&gt;
|-&lt;br /&gt;
|countif||Count the number of answered questions in the list equal the first argument||number countif(matches, arg1, arg2, ... argN)&lt;br /&gt;
|-&lt;br /&gt;
|countifop||Count the number of answered questions in the list which pass the criteria (arg op value)||number countifop(op, value, arg1, arg2, ... argN)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.date.php date]||Format a local date/time||string date(format &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;, timestamp=time()])&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.exp.php exp]||Calculates the exponent of e||number exp(number)&lt;br /&gt;
|-&lt;br /&gt;
|fixnum||Display numbers with comma as radix separator, if needed||string fixnum(number)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.floor.php floor]||Round fractions down||number floor(number)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.gmdate.php gmdate]||Format a GMT date/time||string gmdate(format &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;, timestamp=time()])&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.html-entity-decode.php html_entity_decode]||Convert all HTML entities to their applicable characters (always uses ENT_QUOTES and UTF-8)||string html_entity_decode(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.htmlentities.php htmlentities]||Convert all applicable characters to HTML entities (always uses ENT_QUOTES and UTF-8)||string htmlentities(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.htmlspecialchars.php expr_mgr_htmlspecialchars]||Convert special characters to HTML entities (always uses ENT_QUOTES and UTF-8)||string htmlspecialchars(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.htmlspecialchars-decode.php expr_mgr_htmlspecialchars_decode]||Convert special HTML entities back to characters (always uses ENT_QUOTES and UTF-8)||string htmlspecialchars_decode(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.idate.php idate]||Format a local time/date as integer||string idate(string &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;, timestamp=time()])&lt;br /&gt;
|-&lt;br /&gt;
|if||Excel-style if(test,result_if_true,result_if_false)||if(test,result_if_true,result_if_false)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.implode.php implode]||Join array elements with a string||string implode(glue,arg1,arg2,...,argN)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.intval.php intval]||Get the integer value of a variable||int intval(number &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;, base=10])&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.empty.php is_empty]||Determine whether a variable is considered to be empty||bool is_empty(var)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.is-float.php is_float]||Finds whether the type of a variable is float||bool is_float(var)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.is-int.php is_int]||Find whether the type of a variable is integer||bool is_int(var)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.is-nan.php is_nan]||Finds whether a value is not a number||bool is_nan(var)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.is-null.php is_null]||Finds whether a variable is NULL||bool is_null(var)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.is-numeric.php is_numeric]||Finds whether a variable is a number or a numeric string||bool is_numeric(var)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.is-string.php is_string]||Find whether the type of a variable is string||bool is_string(var)&lt;br /&gt;
|-&lt;br /&gt;
|join{{NewIn|2.0|b=130129}}||Join elements as a new string||join(arg1, arg2, ... argN)&lt;br /&gt;
|-&lt;br /&gt;
|list||Return comma-separated list of non-blank values||string list(arg1, arg2, ... argN)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.log.php log]|| The logarithm of number to base, if given, or the natural logarithm. ||number log(number,base=e)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.ltrim.php ltrim]||Strip whitespace (or other characters) from the beginning of a string||string ltrim(string &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;, charlist])&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.max.php max]||Find highest value||number max(arg1, arg2, ... argN)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.min.php min]||Find lowest value||number min(arg1, arg2, ... argN)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.mktime.php mktime]||Get UNIX timestamp for a date (each of the 6 arguments are optional)||number mktime([hour [, minute [, second [, month [, day [, year ]]]]]])&lt;br /&gt;
|-&lt;br /&gt;
|modulo-function||The modulo function is &#039;&#039;&#039;not supported&#039;&#039;&#039; yet. You can use the floor() function instead||floor(x/y)==(x/y)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.nl2br.php nl2br]||Inserts HTML line breaks before all newlines in a string||string nl2br(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.number-format.php number_format]||Format a number with grouped thousands||string number_format(number)&lt;br /&gt;
|-&lt;br /&gt;
|pi||Get value of pi||number pi()&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.pow.php pow]||Exponential expression||number pow(base, exp)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.quoted-printable-decode.php quoted_printable_decode]||Convert a quoted-printable string to an 8 bit string||string quoted_printable_decode(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.quoted-printable-encode.php quoted_printable_encode]||Convert a 8 bit string to a quoted-printable string||string quoted_printable_encode(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.quotemeta.php quotemeta]||Quote meta characters||string quotemeta(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.rand.php rand]||Generate a random integer, see [[Expression Manager Sample Surveys#Randomly Ask One Question Per Group|this example]]||int rand() OR int rand(min, max)&lt;br /&gt;
|-&lt;br /&gt;
|regexMatch||compare a string to a [[Using regular expressions|regular expression]]||bool regexMatch(pattern,input)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.round.php round]||Rounds a number to an optional precision||number round(val &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;, precision])&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.rtrim.php rtrim]||Strip whitespace (or other characters) from the end of a string||string rtrim(string &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;, charlist])&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.sin.php sin]||Sine||number sin(arg)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.sprintf.php sprintf]||Return a formatted string||string sprintf(format, arg1, arg2, ... argN)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.sqrt.php sqrt]||Square root||number sqrt(arg)&lt;br /&gt;
|-&lt;br /&gt;
|stddev||Calculate the Sample Standard Deviation for the list of numbers||number stddev(arg1, arg2, ... argN)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.str-pad.php str_pad]||Pad a string to a certain length with another string||string str_pad(input, pad_length &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;, pad_string])&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.str-repeat.php str_repeat]||Repeat a string||string str_repeat(input, multiplier)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.str-replace.php str_replace]||Replace all occurrences of the search string with the replacement string||string str_replace(search, replace, subject)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.strcasecmp.php strcasecmp]||Binary safe case-insensitive string comparison||int strcasecmp(str1, str2)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.strcmp.php strcmp]||Binary safe string comparison||int strcmp(str1, str2)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.strip-tags.php strip_tags]||Strip HTML and PHP tags from a string||string strip_tags(str, allowable_tags)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.stripos.php stripos]||Find position of first occurrence of a case-insensitive unicode string (starting by 0, return false if not found)|||int stripos(haystack, needle &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;, offset=0])&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.stripslashes.php stripslashes]||Un-quotes a quoted string||string stripslashes(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.stristr.php stristr]||Case-insensitive strstr||string stristr(haystack, needle &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;, before_needle=false])&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.strlen.php strlen]||Get string length||int strlen(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.strpos.php strpos]||Find position of first occurrence of an unicode string (starting by 0, return false if not found)||int strpos(haystack, needle &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt; offset=0])&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.strrev.php strrev]||Reverse a string||string strrev(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.strstr.php strstr]||Find first occurrence of a string||string strstr(haystack, needle&amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;, before_needle=false])&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.strtolower.php strtolower]||Make a string lowercase||string strtolower(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.strtotime.php strtotime]||Parse about any English textual datetime description into a Unix timestamp||int strtotime(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.strtoupper.php strtoupper]||Make a string uppercase||string strtoupper(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.substr.php substr]||Return part of an unicode string||string substr(string, start &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;, length])&lt;br /&gt;
|-&lt;br /&gt;
|sum||Calculate the sum of values in an array||number sum(arg1, arg2, ... argN)&lt;br /&gt;
|-&lt;br /&gt;
|sumifop||Sum the values of answered questions in the list which pass the criteria (arg op value)||number sumifop(op, value, arg1, arg2, ... argN)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.tan.php tan]||Tangent||number tan(arg)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.time.php time]||Return current UNIX timestamp||number time()&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.trim.php trim]||Strip whitespace (or other characters) from the beginning and end of a string||string trim(string &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;, charlist])&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.ucwords.php ucwords]||Uppercase the first character of each word in a string||string ucwords(string)&lt;br /&gt;
|-&lt;br /&gt;
|unique||Returns true if all non-empty responses are unique||boolean unique(arg1, ..., argN)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Functions that are Planned or Being Considered=== &amp;lt;!--T:176--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:177--&amp;gt;&lt;br /&gt;
Other functions that are planned (or being considered) but which are not implemented yet include the following.  Some of these are for backwards compatability with another survey tool.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:178--&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Syntax!!Meaning!!Comments&lt;br /&gt;
|-&lt;br /&gt;
|e()||returns the value of e||&lt;br /&gt;
|-&lt;br /&gt;
|formatDate(X,PAT)||return the string value of date X formatted according to Java data format pattern PAT||&lt;br /&gt;
|-&lt;br /&gt;
|formatNumber(X,PAT)||return the string value of number X formatted according to Java number format pattern PAT||&lt;br /&gt;
|-&lt;br /&gt;
|getAnsOption(X)||returns the text corresponding to the selected option for answer X||this is the same as X.shown&lt;br /&gt;
|-&lt;br /&gt;
|getAnsOption(X,Y)||returns the text corresponding to the option at index Y of node X||&lt;br /&gt;
|-&lt;br /&gt;
|getRelevance(X)||returns the relevance equation for question X||&lt;br /&gt;
|-&lt;br /&gt;
|getStartTime()||returns the date corresponding to the system time when the interview was started||&lt;br /&gt;
|-&lt;br /&gt;
|getType(X)||returns the string name of the datatype - e.g. *NA* if isNA()||&lt;br /&gt;
|-&lt;br /&gt;
|gotoFirst()||jumps to the first relevant set of questions - this violates the normal flow of the system||&lt;br /&gt;
|-&lt;br /&gt;
|gotoNext()||jumps to the next set of relevant questions - this violates the normal flow of the system||&lt;br /&gt;
|-&lt;br /&gt;
|gotoPrevious()||jumps to the previous set of relevant questions - this violates the normal flow of the system||&lt;br /&gt;
|-&lt;br /&gt;
|isAsked(X)||returns true if the answer is neither *NA*, *INVALID*, nor *UNASKED*||&lt;br /&gt;
|-&lt;br /&gt;
|isInvalid(X)||returns true if the answer is of type *INVALID*||&lt;br /&gt;
|-&lt;br /&gt;
|isNA(X)||returns true if the answer is of type *NA*||&lt;br /&gt;
|-&lt;br /&gt;
|isNotUnderstood(X)||returns true if the answer if of type *HUH*||&lt;br /&gt;
|-&lt;br /&gt;
|isRefused(X)||returns true if the answer is of type *REFUSED*||&lt;br /&gt;
|-&lt;br /&gt;
|isSpecial(X)||returns true if the answer is of type *UNASKED*, *NA*, *REFUSED*, *INVALID*, *UNKNOWN*, or *HUH*||&lt;br /&gt;
|-&lt;br /&gt;
|isUnknown(X)||returns true if the answer is of type *UNKNOWN*||&lt;br /&gt;
|-&lt;br /&gt;
|jumpTo(X)||jump to the group containing the named question -- this violates the normal flow of the system||&lt;br /&gt;
|-&lt;br /&gt;
|jumpToFirstUnasked()||jump to the first unasked question &amp;lt;strike&amp;gt; thus bypassing previous answered questions &amp;lt;/strike&amp;gt; this violates the normal flow of the system||&lt;br /&gt;
|-&lt;br /&gt;
|lastIndexOf(X,Y)||returns the last index (base 0) of string Y in string X. Returns -1 if Y is not contained within X||&lt;br /&gt;
|-&lt;br /&gt;
|list(X,...)||a string containing a comma separated list of the positive values with &amp;quot;and&amp;quot; separating the last two||&lt;br /&gt;
|-&lt;br /&gt;
|mean(X,...)||returns the mean of a list of values||&lt;br /&gt;
|-&lt;br /&gt;
|numAnsOptions(X)||returns the number of answer options that question X has||&lt;br /&gt;
|-&lt;br /&gt;
|orlist(X,...)||a string containing a comma separated list of the positive values, with &amp;quot;or&amp;quot; separting the last two||&lt;br /&gt;
|-&lt;br /&gt;
|parseDate(X,PAT)||returns the date value of string X parsed with Java date format pattern PAT||&lt;br /&gt;
|-&lt;br /&gt;
|parseNumber(X,PAT)||returns the numerical value of string X parsed with Java number format pattern PAT||&lt;br /&gt;
|-&lt;br /&gt;
|showAllResponsesExcept( questionList,attributeList,attributeTitleList)||questionList = pipe-delimited list of question identifiers; attributeList = pipe-delimited list of attributes (like question#, title, text, type - so you can decide what to show); attributeTitleList = pipe-delimited list of table headers, so can internationalize the report.||&lt;br /&gt;
|-&lt;br /&gt;
|showTheseResponses( questionList,attributeList,attributeTitleList)||questionList = pipe-delimited list of question identifiers; attributeList = pipe-delimited list of attributes (like question#, title, text, type - so you can decide what to show); attributeTitleList = pipe-delimited list of table headers, so can internationalize the report.|| &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Expression Manager Knows Which Variables are Local== &amp;lt;!--T:179--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:180--&amp;gt;&lt;br /&gt;
In order to properly build the JavaScript for page, Expression Manager needs to know which variables are set on the page, and what their JavaScript ID is (e.g. for document.getElementById(x)).  It also must know which variables are set on other pages (so that it can ensure that the needed &amp;lt;input type=&#039;hidden&#039; value=&#039;x&#039;&amp;gt; fields are present and populated).&lt;br /&gt;
&lt;br /&gt;
==Cascading Conditions== &amp;lt;!--T:181--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:182--&amp;gt;&lt;br /&gt;
If any of the variables are irrelevant, the whole equation will be irrelevant (false).  For example, in the following table, N/A means that one of the variables was not relevant&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:183--&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Operator!!Example!!a!!b!!Result&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;+ (unary)&amp;lt;/nowiki&amp;gt;||&amp;lt;nowiki&amp;gt;+a&amp;lt;/nowiki&amp;gt;||N/A|| ||false&lt;br /&gt;
|-&lt;br /&gt;
|- (unary)||-a||N/A|| ||false&lt;br /&gt;
|-&lt;br /&gt;
|!||!a||N/A|| ||false&lt;br /&gt;
|-&lt;br /&gt;
|== (or eq)||a == b||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|== (or eq)||a == b||N/A||0||false&lt;br /&gt;
|-&lt;br /&gt;
|== (or eq)||a == b||N/A||N/A||false&lt;br /&gt;
|-&lt;br /&gt;
|!= (or ne)||a != b||N/A||5|| false&lt;br /&gt;
|-&lt;br /&gt;
|!= (or ne)||a != b||N/A||N/A|| false&lt;br /&gt;
|-&lt;br /&gt;
|!= (or ne)||a != b||N/A||0||false&lt;br /&gt;
|-&lt;br /&gt;
|&amp;gt; (or gt)||a &amp;gt; b||N/A||5|| false&lt;br /&gt;
|-&lt;br /&gt;
|&amp;gt;= (or ge)||a &amp;gt;= b||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt; (or lt)||a &amp;lt; b||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;= (or le)||a &amp;lt;= b||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|and||a and b||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|and||a and b||N/A||N/A||false&lt;br /&gt;
|-&lt;br /&gt;
|or||a or b||N/A||N/A||false&lt;br /&gt;
|-&lt;br /&gt;
|or||a or b||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;+&amp;lt;/nowiki&amp;gt;||a + b||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|-||a - b||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|*||a * b||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|/||a / b||5||N/A||false&lt;br /&gt;
|-&lt;br /&gt;
|()||(a)||N/A|| ||false&lt;br /&gt;
|-&lt;br /&gt;
|(exp)||(a &amp;amp;&amp;amp; b)||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|(exp) op (exp)||(b + b) &amp;gt; (a &amp;amp;&amp;amp; b)||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|function||sum(a,b,b)||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|function||max(a,b)||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|function||min(a,b)||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|function||implode(&#039;, &#039;,a,b,a,b)||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|function||if(a,a,b)||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|function||is_empty(a)||N/A|| ||false&lt;br /&gt;
|-&lt;br /&gt;
|function||is_empty(a)||0 (or blank)|| ||true&lt;br /&gt;
|-&lt;br /&gt;
|function||!is_empty(a)||N/A|| ||false&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Overriding Cascading Conditions=== &amp;lt;!--T:184--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:185--&amp;gt;&lt;br /&gt;
Say you want to show a running total of all relevant answers.  You might try to use the equation {sum(q1,q2,q3,...,qN)}.  However, this gets translated internally to LEMif(LEManyNA(&#039;q1&#039;,&#039;q2&#039;,&#039;q3&#039;,...,&#039;qN&#039;),&#039;&#039;,sum(LEMval(&#039;q1&#039;),LEMval(&#039;q2&#039;),LEMval(&#039;q3&#039;),...,LEMval(&#039;qN&#039;))).  So, if any of the values q1-qN are irrelevant, the equation will always return false.  In this case, the sum() will show 0 until all questions are answered.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:186--&amp;gt;&lt;br /&gt;
To get around this, each variable can have a &amp;quot;.NAOK&amp;quot; suffix (meaning that Not Applicable is OK) added to it.  In such cases, the following behavior occurs.  Say you have a variable q1.NAOK&lt;br /&gt;
#q1 is not added to the LEManyNA() clause&lt;br /&gt;
#LEMval(&#039;q1&#039;) will  continue to check whether the response is relevant, and will return &amp;lt;nowiki&amp;gt;&#039;&#039;&amp;lt;/nowiki&amp;gt; if it is not (so individual irrelevant responses will be ignored, but they will not void the entire expression).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:187--&amp;gt;&lt;br /&gt;
So, the solution to the running total problem is to use the equation sum(q1.NAOK,q2.NAOK,q3.NAOK,...,qN.NAOK).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:188--&amp;gt;&lt;br /&gt;
The use of the .NAOK suffix also lets authors design surveys that have several possible paths but then converge on common paths later.  For example, say subjects answer a survey in a way that is outside the normal range of responses.  The author could alert the subjects that they may not get valid results, and ask them whether they really want to  continue with the survey.  If they say Yes, then the rest of the questions will be shown.  The condition for the &amp;quot;rest of the questions&amp;quot; would check whether the initial responses were answered within the normal range OR whether the subject said Yes to the question that is only relevant if they answered outside the normal range.&lt;br /&gt;
&lt;br /&gt;
==How does Expression Manager Support Conditional Micro-Tailoring?== &amp;lt;!--T:189--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:190--&amp;gt;&lt;br /&gt;
Here is an example of micro-tailoring (where Question Type==&#039;expr&#039; means an Equation):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:191--&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Question Code!!Relevance!!Question Type!!Question&lt;br /&gt;
|-&lt;br /&gt;
|name||1||text||What is your name?&lt;br /&gt;
|-&lt;br /&gt;
|age||1||text||How old are you?&lt;br /&gt;
|-&lt;br /&gt;
|badage||!is_empty(age)||expr||{(age&amp;lt;16) or (age&amp;gt;80)}&lt;br /&gt;
|-&lt;br /&gt;
|agestop||badage||message||Sorry, {name}, you are too {if( (age&amp;lt;16),&#039;young&#039;,if( (age&amp;gt;80),&#039;old&#039;,&#039;middle-aged&#039;) ) } for this test.&lt;br /&gt;
|-&lt;br /&gt;
|kids||!badage||yesno||Do you have children?&lt;br /&gt;
|-&lt;br /&gt;
|parents||1||expr||{!badage &amp;amp;&amp;amp; kids==&#039;Y&#039;}&lt;br /&gt;
|-&lt;br /&gt;
|numKids||parents||text||How many children do you have?&lt;br /&gt;
|-&lt;br /&gt;
|kid1||parents &amp;amp;&amp;amp; numKids &amp;gt;= 1||text||How old is your first child?&lt;br /&gt;
|-&lt;br /&gt;
|kid2||parents &amp;amp;&amp;amp; numKids &amp;gt;= 2||text||How old is your second child?&lt;br /&gt;
|-&lt;br /&gt;
|kid3||parents &amp;amp;&amp;amp; numKids &amp;gt;= 3||text||How old is your third child?&lt;br /&gt;
|-&lt;br /&gt;
|kid4||parents &amp;amp;&amp;amp; numKids &amp;gt;= 4||text||How old is your fourth child?&lt;br /&gt;
|-&lt;br /&gt;
|kid5||parents &amp;amp;&amp;amp; numKids &amp;gt;= 5||text||How old is your fifth child?&lt;br /&gt;
|-&lt;br /&gt;
|sumage||1||expr||{sum(kid1.NAOK,kid2.NAOK,kid3.NAOK,kid4.NAOK,kid5.NAOK)}&lt;br /&gt;
|-&lt;br /&gt;
|report||parents||yesno||{name}, you said you are {age} and that you have {numKids}.  The sum of ages of your first {min(numKids,5)} kids is {sumage}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:192--&amp;gt;&lt;br /&gt;
All of these questions can be on a single page (e.g. in the same group), and only the relevant questions will display.  Moreover, as you enter the ages of children, the sum() expression in the last question will dynamically update on the page.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:193--&amp;gt;&lt;br /&gt;
Expression Manager provides this functionality by surrounding each expression with a named &amp;lt;span&amp;gt; element.  Every time a value changes, it recomputes the expression that should appear in that &amp;lt;span&amp;gt; element and regenerates the display.  You can have dozens, or even hundreds, of such tailored expressions on the same page, and the page will re-display all of them in a single screen refresh.&lt;br /&gt;
&lt;br /&gt;
==Mapping of LimeSurvey 1.91+ to Expression Manager Functionality== &amp;lt;!--T:194--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:195--&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Old Feature!!New Feature!!Comments&lt;br /&gt;
|-&lt;br /&gt;
|Conditions||Relevance||You can use very complex conditional equations, and access a broader range of variables&lt;br /&gt;
|-&lt;br /&gt;
|Assessments||Equation||Any assessment scores can be re-structured into an Equation. This both ensures that the score is written to the database, and also lets you see dynamic changes to the score value on the current page&lt;br /&gt;
|-&lt;br /&gt;
|Replacements||Expression Manager||The core engine takes the input string and treats everything within curly braces as an Expression - so it handles all historical replacements types.  To avoid messing up embedded JavaScript, Expression Manager only processes content between curly braces as long as (a)  there is no leading or trailing whitespace within the curly braces - e.g. {expr} is an expression, but { expr}, {expr }, and { expr } are not expressions.  Furthermore, Expression Manager does not process content within its own strings (e.g. {list(&#039;hi&#039;,&#039;there {braces}&#039;)} generates &amp;quot;hi there {braces}&amp;quot;).  It also ignores escaped curly braces (e.g. \{this is not an expression\})&lt;br /&gt;
|-&lt;br /&gt;
|Validation||Expression Manager||The plan is to take the current min/max Question Attributes and have Expression Manager process them.  That way the min/max values can be expressions themselves&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Syntax Highlighting= &amp;lt;!--T:196--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:197--&amp;gt;&lt;br /&gt;
To help with entering and validating expressions, EM provides syntax highlighting with the following features:&lt;br /&gt;
&lt;br /&gt;
==Types and Meanings of Syntax Highlighting== &amp;lt;!--T:198--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:199--&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Color!!Sample!!Meaning!!Tooltip!!Comments&lt;br /&gt;
|-&lt;br /&gt;
|tan background||style=&#039;background-color: #eee8aa&#039;|Sample||the whole equation||none||Anything within curly braces that is recognized as an equation (e.g. there is no leading or trailing whitepace) will be color-coded with a tan background to help distinguish it from surrounding text&lt;br /&gt;
|-&lt;br /&gt;
|bold red text||style=&#039;color:#ff0000; background-color:#eee8aa&#039;|&#039;&#039;&#039;Sample&#039;&#039;&#039;||An error||Some explanation on error||Can be an unknow variable or an error in function, .... Survey can be totally broken, this don&#039;t show to public user.&lt;br /&gt;
|-&lt;br /&gt;
|blue text||style=&#039;color:#0000ff; background-color:#eee8aa&#039;|Sample||function name||meaning and allowable syntax||function names, or things that should be functions since they are followed by an opening parenthesis, are presented in bold blue text.  Tooltips show the meaning and allowable syntax for the function.&lt;br /&gt;
|-&lt;br /&gt;
|grey text||style=&#039;color:#808080; background-color:#eee8aa&#039;|Sample||string||none||single and double-quoted strings are shown in grey text&lt;br /&gt;
|-&lt;br /&gt;
|cyan text||style=&#039;color:#4169e1; background-color:#eee8aa&#039;|Sample||variable set on the same page,||&amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;name or SGQA code]: question; value; answerList showing codes for each value||Any variable that is set on the same page to the current question is shown in cyan text, showning it can be updated in javascript.  The tooltip shows its name (if you used INSERTANS:xxx) or SGQA code (if you used the new naming system), the actual question, and its current value (or blank if not set).  If the question type expects responses from an enumerated value set, the mapping of the codes to display values is show.&lt;br /&gt;
|-&lt;br /&gt;
|green text||style=&#039;color:#008000; background-color:#eee8aa&#039;|Sample||variable set on a prior page||&amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;name or SGQA code]: question; value; answerList showing codes for each value||Any variable that is set on a prior page is shown in bold green text.  The tooltip shows its name (if you used INSERTANS:xxx) or SGQA code (if you used the new naming system), the actual question, and its current value (or blank if not set).  If the question type expects responses from an enumerated value set, the mapping of the codes to display values is show.&lt;br /&gt;
|-&lt;br /&gt;
|bold pink text||style=&#039;color:#9370db; background-color:#eee8aa&#039;|Sample||variable set on a later page &amp;lt;sup&amp;gt;in general : empty at survey start, but can be filled with index or move previous&amp;lt;/sup&amp;gt;||&amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;name or SGQA code]: question; value; answerList showing codes for each value||Any variable that is set on a prior page is shown in bold pink text.  These are erorrs since the variable is  being used before it is declareed.  The tooltip shows its name (if you used INSERTANS:xxx) or SGQA code (if you used the new naming system), the actual question, and its current value (or blank if not set).  If the question type expects responses from an enumerated value set, the mapping of the codes to display values is show.&lt;br /&gt;
|-&lt;br /&gt;
|bold tan text||style=&#039;color:#a0522d; background-color:#eee8aa&#039;|Sample||a lime replacement value||the value||Lime Replacement Strings (like {TOKEN:xxx}, {PRIVACY_MESSAGE}) are shown in bold tan text.  &lt;br /&gt;
|-&lt;br /&gt;
|red text||style=&#039;color:#ff4500; background-color:#eee8aa&#039;|Sample||assignment operator (=) ||warning message||If you use one of the assignment operator (=) that operator will be displayed in red text.  This is meant to help prevent accidental re-assignment of values when you really meant to check whether a == b instead of  setting the value of a = b.&lt;br /&gt;
|-&lt;br /&gt;
|normal black text||style=&#039;color:black; background-color:#eee8aa&#039;|Sample||punctuation||none||All other punctuation within the expression is shown as normal black text.&lt;br /&gt;
|-&lt;br /&gt;
|red-boxed text||a bold red line surrounds the error||syntax error||description of the error||Any detected syntax errors are shown by surrounding the error with a red box.  The tooltip shows the error.  Examples include unmatched parentheses, use of undefined functions, passing the wrong number of arguments to functions, poorly structured expressions (e.g. missing operators between variables), trying to assign a new value to a read-only variable, trying to assign values to non-variables, or using unsupported syntax.  Note that the syntax error dectection system may only report one error in an expression even if there are multiple errors; however, if any errors are detected, at least one error will be shown.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Additional Reading= &amp;lt;!--T:202--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==[[Expression Manager Sample Surveys|Expression Manager Sample Surveys]]== &amp;lt;!--T:203--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==[[Expression Manager HowTos|Use Cases and HowTos]]== &amp;lt;!--T:204--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==[[Expression Manager Examples|Step-by-Step Examples]].== &amp;lt;!--T:205--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==[[Expression Manager for developers|Reference for Developers]]== &amp;lt;!--T:206--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==[[Expression Manager Roadmap|RoadMap/Status/ToDo List]]== &amp;lt;!--T:207--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/translate&amp;gt;&lt;/div&gt;</summary>
		<author><name>LimeAJ</name></author>
	</entry>
	<entry>
		<id>https://www.limesurvey.org/manual/index.php?title=Expression_Manager&amp;diff=74065</id>
		<title>Expression Manager</title>
		<link rel="alternate" type="text/html" href="https://www.limesurvey.org/manual/index.php?title=Expression_Manager&amp;diff=74065"/>
		<updated>2017-07-28T20:37:40Z</updated>

		<summary type="html">&lt;p&gt;LimeAJ: Improved explanation of the meaning for &amp;quot;NAOK&amp;quot;.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;languages /&amp;gt; &amp;lt;translate&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:1--&amp;gt;&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:2--&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;simplebox&amp;quot;&amp;gt; Note: This feature is only available in LimeSurvey 1.92 or later. &amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Quick Start Tutorial= &amp;lt;!--T:3--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Overview== &amp;lt;!--T:4--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:5--&amp;gt;&lt;br /&gt;
When customizing your surveys, you typically need a way to specify the following:&lt;br /&gt;
#&#039;&#039;&#039;Navigation/Branching&#039;&#039;&#039; - letting a subject&#039;s answers change the order in which questions are asked&lt;br /&gt;
#&#039;&#039;&#039;Tailoring/Piping&#039;&#039;&#039; - how to phrase the question (such as referring to prior answers, or conjugating sentences based upon the number or gender of your subjects), or how to generate custom reports (like assessment scores or tailored advice).&lt;br /&gt;
#&#039;&#039;&#039;Validation&#039;&#039;&#039; - ensuring that answers pass certain criteria, like min and max values, or matching an input pattern&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:6--&amp;gt;&lt;br /&gt;
Expression Manager (EM) provides an intuitive way to specifying the logic for each of those features.  Nearly anything that you can write as a standard mathematical equation is a valid expression, even if you are calling functions.  EM currently provides access to 70 functions, and can be easily extended to support more.  It also lets you access your variables using human-readable variable names (rather than SGQA names).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:7--&amp;gt;&lt;br /&gt;
The following sections show the main places where Expression Manager is used&lt;br /&gt;
&lt;br /&gt;
==Relevance (Controlling Navigation/Branching)== &amp;lt;!--T:8--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:9--&amp;gt;&lt;br /&gt;
Some surveys use &amp;quot;Goto Logic&amp;quot;, such that if you answer Question 1 with option C, then jump to Question 5. This approach is very limiting, since is hard to validate, and easily breaks if you have to re-order questions.  EM uses a Boolean relevance equation to specify all of the conditions under which a question might be valid.  If the question is relevant, then the question is asked, otherwise it is Not Applicable, and the value NULL is stored in the database.  This is similar to what can be done via the Conditions editor, but EM lets you easily specify much more complex and powerful criteria (and lets you use the variable name rather than SGQA naming).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:10--&amp;gt;&lt;br /&gt;
This image shows one way to review the relevance logic for a survey.  It computes Body Mass Index.  The relevance equation is shown in square bracket right after the variable name (which is in green).  So, the relevance of weight, weight_units, height and height_units are all 1, meaning that those questions are always asked.  However, the relevance for BMI is {!is_empty(height) and !is_empty(weight)}, which means that BMI will only be computed if the subject enters a value for both height and weight (thereby avoiding the risk of a divide by zero error).  Also, the Report question is only shown if the subject answers all four main questions (height, height_units, weight, weight_units).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:11--&amp;gt;&lt;br /&gt;
[[File:tutorial1.jpg]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:12--&amp;gt;&lt;br /&gt;
Relevance is shown and editable in the following places:&lt;br /&gt;
&lt;br /&gt;
===Viewing / Editing Question-Level Relevance=== &amp;lt;!--T:13--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:14--&amp;gt;&lt;br /&gt;
This equation computes the Body Mass Index (BMI).  It is only asked if the person first enters their height and weight.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:15--&amp;gt;&lt;br /&gt;
[[File:tutorial2.jpg]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:16--&amp;gt;&lt;br /&gt;
This is the edit screen for the BMI question.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:17--&amp;gt;&lt;br /&gt;
[[File:tutorial3.jpg]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:18--&amp;gt;&lt;br /&gt;
Note that you do not use the curly braces when you enter a Relevance Equation.&lt;br /&gt;
&lt;br /&gt;
===Viewing / Editing Group-Level Relevance=== &amp;lt;!--T:19--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:20--&amp;gt;&lt;br /&gt;
This is a sample census survey.  The first page asks how many people live with you and stores that in the &amp;quot;cohabs&amp;quot; variable.  This page is only shown if you have more than one cohabitant (so it is shown for the second person cohabitating with you), and also only shows if you specified how Person One is related to you (p1_rel).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:21--&amp;gt;&lt;br /&gt;
[[File:tutorial4.jpg]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:22--&amp;gt;&lt;br /&gt;
As you can see, the group also has question-level relevance criteria, such that each question only appears once you have answered the question before it (e.g. {!is_empty(p1_sex)}).  EM combines the Group and Question-level relevance for you.  Questions in a group are only asked  if the group as a whole is relevant.  Then, only the subset of questions within the group that are relevant are asked.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:23--&amp;gt;&lt;br /&gt;
Here is the screen for editing the group-level relevance for that question:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:24--&amp;gt;&lt;br /&gt;
[[File:tutorial5.jpg]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:25--&amp;gt;&lt;br /&gt;
Note that you do not use the curly braces when you enter a Relevance Equation.&lt;br /&gt;
&lt;br /&gt;
==Tailoring/Piping== &amp;lt;!--T:26--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:27--&amp;gt;&lt;br /&gt;
EM lets you easily do simple and complex conditional tailoring of your questions.  Sometimes you just need simple substitution, like saying, &amp;quot;You said you purchased &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;Product].  What did you like best about it?&amp;quot;.  Sometimes you need conditional substitution like &amp;quot;&amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;Mr./Mrs.] &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;LastName], would you be willing to complete our survey?&amp;quot;.  In this case,  you want to use Mr. or Mrs. based upon the person&#039;s gender.  Other times you need even more complex substitution (such as based upon a mathematical computation).  EM supports each of these types of tailoring/piping.&lt;br /&gt;
&lt;br /&gt;
===Conditional Equations=== &amp;lt;!--T:28--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:29--&amp;gt;&lt;br /&gt;
The Body Mass Index example shows the ability to compute a person&#039;s BMI, even while letting them enter their height in weight in metric or non-metric units.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:30--&amp;gt;&lt;br /&gt;
[[File:tailoring7.jpg]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:31--&amp;gt;&lt;br /&gt;
Here weight_kg is {if(weight_units == &#039;kg&#039;, weight, weight * .453592)}.  This if() function means that if the subject entered the weight using kilograms, use that value, otherwise multiple the entered value (which was in pounds) by .453592 to convert it to kilograms.  The height_m variable uses a similar approach to compute the person&#039;s height in meters, even if he entered his height in inches.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:32--&amp;gt;&lt;br /&gt;
BMI computes the weight formula as {weight_kg / (height_m * height_m)}.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:33--&amp;gt;&lt;br /&gt;
Lastly, the report conditionally tailors the message for the subject, telling him what he entered. (&amp;quot;You said you are 2 meters tall and weight 70 kg.&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:34--&amp;gt;&lt;br /&gt;
Although not well shown in the above image, weight_status uses nested if() statements to categorize the person as underweight to severely obese.  You can see its equation in the Show Logic View&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:35--&amp;gt;&lt;br /&gt;
[[File:tailoring8.jpg]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:36--&amp;gt;&lt;br /&gt;
From the edit window for this question, you can see two things:&lt;br /&gt;
#Tailoring must surround expressions with Curly Braces&lt;br /&gt;
#Expressions can span multiple lines if, as in this case, you want to make it easier to read the nested conditional logic.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:37--&amp;gt;&lt;br /&gt;
[[File:tailoring9.jpg]]&lt;br /&gt;
&lt;br /&gt;
===Tailored Questions, Answers, and Reports=== &amp;lt;!--T:38--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:39--&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;simplebox&amp;quot;&amp;gt;Note: Dynamic tailoring may not work if answer options are made available in select boxes on the same question page. This results from the fact that tailoring inserts a &amp;lt;nowiki&amp;gt;&amp;lt;span&amp;gt;&amp;lt;/nowiki&amp;gt; tag which is not valid inside select options.&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:40--&amp;gt;&lt;br /&gt;
This example shows the BMI report.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:41--&amp;gt;&lt;br /&gt;
[[File:tailoring10.jpg]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:42--&amp;gt;&lt;br /&gt;
Here is the edit window for the same question.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:43--&amp;gt;&lt;br /&gt;
[[File:tailoring11.jpg]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:44--&amp;gt;&lt;br /&gt;
As you can see, anything in curly braces is treated as an expression, so is syntax-highlighted (color coded) in the prior image.  If you had any typos (such as misspelled or undefined variable names or functions), EM would show an error, such as this, showing that height_unit is an undefined variable name (it is actually height_units), and rnd() is an undefined function (the proper function name is round()).  In both cases, the errors are surrounded by a red box to make it easier to spot and fix them.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:45--&amp;gt;&lt;br /&gt;
[[File:tailoring12.jpg]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:46--&amp;gt;&lt;br /&gt;
You can also see that you can quickly create complex reports, such as a table of entered values or tailored advice.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:47--&amp;gt;&lt;br /&gt;
Please remember that all tailoring must surround expressions with Curly Braces, so that LimeSurvey knows which parts of the question are free text and which should be parsed through Expression Manager.&lt;br /&gt;
&lt;br /&gt;
==Validation== &amp;lt;!--T:48--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:49--&amp;gt;&lt;br /&gt;
EM controls how most of the advanced question options work.  These control aspects like min/max numbers of answers; min/max individual values; min/max sum values; and checking that entered values match specified string patterns.  You continue to enter those advanced question options as usual.  However, now any value in one of those fields is considered an expression, so you can have min/max criteria with complex conditional relationships to other questions.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:50--&amp;gt;&lt;br /&gt;
In all of these cases, since the advanced question option is always considered an expression, you do not use curly braces when specifying it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:51--&amp;gt;&lt;br /&gt;
The [[Expression Manager Sample Surveys|Sample Surveys]] pages shows many working examples of using expressions for validations.&lt;br /&gt;
&lt;br /&gt;
=Introduction= &amp;lt;!--T:52--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:53--&amp;gt;&lt;br /&gt;
LimeSurvey uses the new Expression Manager (EM) module which will let LimeSurvey support more complex branching, assessments, validation, and tailoring.  It will replace how LimeSurvey manages Replacements, Conditions, and Assessments on the back-end.  It will also speed up processing considerably since it eliminates most run-time database reads.  EM was developed by Dr. Thomas White (TMSWhite).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:54--&amp;gt;&lt;br /&gt;
This wiki page is the definitive reference for Expression Manager syntax and functionality.&lt;br /&gt;
&lt;br /&gt;
==Key Definitions== &amp;lt;!--T:55--&amp;gt;&lt;br /&gt;
#&#039;&#039;&#039;Expression&#039;&#039;&#039;:  Anything surrounded by curly braces&lt;br /&gt;
#*As long as there is no white space immediately after the opening brace or before the closing curly brace&lt;br /&gt;
#*The contents of Expressions are evaluted by EM, so they can contain mathematical formulas, functions, and complex string and date processing.&lt;br /&gt;
#&#039;&#039;&#039;Tailoring&#039;&#039;&#039;: Sometimes called &amp;quot;piping&amp;quot;, this is the process of conditionally modifying text&lt;br /&gt;
#*You have access to all &#039;replacement fields&#039;, TOKENs, and INSERTANS values&lt;br /&gt;
#*You also have easier access to questions, answers, and their properties.&lt;br /&gt;
#&#039;&#039;&#039;Relevance&#039;&#039;&#039; Equation:  A new question attribute controlling question visiblity&lt;br /&gt;
#*If there is a relevance equation, then the question is only shown if the relevance evaluates to true.&lt;br /&gt;
#*Internally, all array_filter and array_filter_exclude commands become sub-question-level relevance&lt;br /&gt;
#&#039;&#039;&#039;Equation&#039;&#039;&#039; Question Type:  A new question type that saves calculations or reports to the database&lt;br /&gt;
#*It is like a Boilerplate question, but its contents are saved to the database even if you set &amp;quot;Always Hide this Question&amp;quot;&lt;br /&gt;
#&#039;&#039;&#039;Question Code&#039;&#039;&#039;:  This is the preferred variable name for EM&lt;br /&gt;
#*This can be a descriptive name indicating the purpose of the question, making it easier to read complex logic&lt;br /&gt;
#*Valid question codes should NOT start with a number, so when using the question code to number your questions, simply use &amp;quot;q1&amp;quot;, or &amp;quot;q1a&amp;quot; or &amp;quot;g1q2&amp;quot;.&lt;br /&gt;
#*This is what currently becomes the variable name if you export data to SPSS or R, so if you do statistical analysis, you probably already made this unique.&lt;br /&gt;
&lt;br /&gt;
==Do I have to use EM?== &amp;lt;!--T:56--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:57--&amp;gt;&lt;br /&gt;
The short answer is No (but also yes).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:58--&amp;gt;&lt;br /&gt;
EM is fully backwards-compatible with existing surveys.  So, if you are happy to use Conditions and Assessments in the style that LimeSurvey used in versions &amp;lt;= 1.91+, you can continue to do so.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:59--&amp;gt;&lt;br /&gt;
However, EM completely replaces how LimeSurvey internally deals with Conditions.  Although you can still use the Conditions Editor to create and manage conditions, LimeSurvey 1.92 will convert those to the equivalent Relevance Equations.  As part of the upgrade, LimeSurvey 1.92 will auto-convert all existing Conditions to Relevance Equations.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:60--&amp;gt;&lt;br /&gt;
This should give you the best of both worlds - you can continue using LimeSurvey as you are used to, but will see the Relevance Equation equivalent so you can gradually migrate to Relevance Equations directly whenever you see fit.&lt;br /&gt;
&lt;br /&gt;
==Can I mix use of Conditions and Relevance?== &amp;lt;!--T:61--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:62--&amp;gt;&lt;br /&gt;
Yes. You can use the Conditions editor for some questions and the Relevance editor for others.  Conditions are auto-converted to Relevance when you save the question.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:63--&amp;gt;&lt;br /&gt;
Note, we assume that if you are using the Conditions editor, that you want those Conditions to over-write any manually entered Relevance equation.  So, if you have existing Conditions and want to manually edit the Relevance, please delete the Conditions for that question first.  Specifically, copy the generated relevance equation to a text editor, use the Conditions menu to delete all of the conditions for that question (which will also delete the relevance), then edit the question and paste the generated relevance equation from the text editor back into the relevance field for that question (and save the question).  If there is enough demand for deleting conditions without deleting the generated relevance equation, we could add a bulk conversion process.&lt;br /&gt;
&lt;br /&gt;
==How should I choose between Conditions and Relevance?== &amp;lt;!--T:64--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:65--&amp;gt;&lt;br /&gt;
Here is a list of pros and cons of each style:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:66--&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Style!!Pros!!Cons&lt;br /&gt;
|-&lt;br /&gt;
|Conditions||1. Nice GUI for creating simple conditions &amp;lt;br/&amp;gt;2. GUI well documented and understood by support team||1. Only supports simple comparisons and does not AND/OR conditions well &amp;lt;br/&amp;gt;2. Cascading conditions work erratically &amp;lt;br/&amp;gt;3. Slow - database intensive, so can slow down long surveys &amp;lt;br/&amp;gt;4. Some reported problems with re-loading conditions &amp;lt;br/&amp;gt;5. GUI doesn&#039;t scale well when there are dozens, hundreds, or thousands of questions &amp;lt;br/&amp;gt;6. May be slow to convert paper-based surveys since must use SGQA names &amp;lt;br/&amp;gt;7. Often need a programmer to custom-code logic needed for complex branching&lt;br /&gt;
|-&lt;br /&gt;
|Relevance||1. Supports very complex logic, including 80+ functions and math/string operators &amp;lt;br/&amp;gt;2. Perfect support for cascading logic &amp;lt;br/&amp;gt;3. Fast - no extra database calls, so supports 1000+ question surveys &amp;lt;br/&amp;gt;4. No problems with re-loading logic since does not require SGQA codes &amp;lt;br/&amp;gt;5. Syntax-highlighting scales to 1000+ question surveys &amp;lt;br/&amp;gt;6. Easy and fast to use for groups wanting to computerize existing paper-based suveys.  &amp;lt;br/&amp;gt;7. Easily supports semi-structured interviews and epidemiological surveys without needing a programmers||1. No GUI for simple conditions - use syntax-highlighting instead &amp;lt;br/&amp;gt;2. New, so support teams have not mastered EM yet.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:67--&amp;gt;&lt;br /&gt;
The bottom is that if you are happy with how LimeSurvey 1.91+ works, there is no reason to change what you do.&lt;br /&gt;
&lt;br /&gt;
==What are some other benefits of using EM?== &amp;lt;!--T:68--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:69--&amp;gt;&lt;br /&gt;
Here are some of the other reasons you might want to use EM.&lt;br /&gt;
#Calculations - you can create any calculation you can think of:&lt;br /&gt;
#*You have access to all common mathematical operators and functions&lt;br /&gt;
#*You have access to 70+ mathematical, date, and string processing functions&lt;br /&gt;
#*It is fairly easy for developers to add new functions if users need them&lt;br /&gt;
#Storing Calculations to Database&lt;br /&gt;
#*You can now compute simple and complex calculations and/or scale scores AND have them stored in the database without needing JavaScript.&lt;br /&gt;
#*You use the Equation question type to accomplish this.&lt;br /&gt;
#Assessments&lt;br /&gt;
#*You can now create assessments or scale scores from any question type, not just the subset that used to be supported&lt;br /&gt;
#*You can use Tailoring to show running or total assessment scores anywhere needed - even on the same page&lt;br /&gt;
#*You have more control over the reports generated based upon those assessment scores&lt;br /&gt;
#*You can store assessment scores in the database without needing JavaScript&lt;br /&gt;
#*You can hide assessment scores without needing JavaScript or CSS&lt;br /&gt;
#Replacement Fields&lt;br /&gt;
#*Instead of using {INSERTANS:SGQA}, you can just use the Question Code - this makes it easier to read and validate.&lt;br /&gt;
#*This also avoids the common need to edit questions to change the SGQA code to make everything work.&lt;br /&gt;
#Tailoring - you can conditionally display text based upon other values&lt;br /&gt;
#*Use the appropriate title for a subject, like (e.g. &amp;quot;Hello &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;Mr./Mrs.] Smith&amp;quot;)&lt;br /&gt;
#*Output gramatically correct sentences based when singular/plural matter:  (e.g. &amp;quot;You have 1 child&amp;quot; vs. &amp;quot;You have 2 children&amp;quot;)&lt;br /&gt;
#*Appropriately conjugate verbs and decline nouns based upon subject&#039;s gender and plurality.&lt;br /&gt;
#New Variable Attributes - you can access the following to do your tailoring:&lt;br /&gt;
#* (no suffix) -  an alias for qcode.code&lt;br /&gt;
#*.code - the selected response code for the question if it is relevant (otherwise blank), or the text value if it is not a coded question&lt;br /&gt;
#*.NAOK - same as .code, but can be part of calculations or lists even if irrelevant&lt;br /&gt;
#*.value - the assessment value for the question if it is relevant (otherwise blank), or the text value if it is not a coded question&lt;br /&gt;
#*.valueNAOK - same as .value, but can be part of calculations or lists even if irrelevant&lt;br /&gt;
#*.shown - the answer as displayed to the user (this is what {INSERTANS:xxx}  does)&lt;br /&gt;
#*.qid - the question ID&lt;br /&gt;
#*.gid - the group ID&lt;br /&gt;
#*.sgqa - the SGQA value for the question&lt;br /&gt;
#*.jsName - the correct javascript variable name for the question, regardless whether defined on this page or another&lt;br /&gt;
#*.qseq - the question sequence (starting from 0)&lt;br /&gt;
#*.gseq - the group sequence (starting from 0)&lt;br /&gt;
#*.mandatory - whether the question is mandatory (Y/N)&lt;br /&gt;
#*.question - the text of the question&lt;br /&gt;
#*.relevance - the relevance equation for the question&lt;br /&gt;
#*.grelevance - the relevance equation for the group&lt;br /&gt;
#*.relevanceStatus - whether or not the question is currently relevant (1 if true, 0 if false)&lt;br /&gt;
#*.type - the question type (the one character code)&lt;br /&gt;
#Dynamic On-Page Changes&lt;br /&gt;
#*All Relevance, Calculation, and Tailoring works dynamically on a page - so changes in values instantly update the page&lt;br /&gt;
#*So, you have questions dynamically appear/disappear based upon whether they are relevant&lt;br /&gt;
#*Questions are also dynamically tailored based upon responses on the page, so you can see running totals, tailored sentences and customized reports.&lt;br /&gt;
#New Data Entry Screen&lt;br /&gt;
#*In addition to using the current data-entry system, you can just use Survey-All-In-One.&lt;br /&gt;
#*This supports the on-page relevance and tailoring, so data entry clerks can quickly tab through and they will only have to enter the relevant responses&lt;br /&gt;
#*This can be critical if your data entry person needs to see the tailoring, which is also dynamic.&lt;br /&gt;
#Eliminates the need for most custom JavaScript&lt;br /&gt;
#*EM easily supports complicated computations, scoring, tailoring and conditional logic.&lt;br /&gt;
#*Some things will still need JavaScript (like custom layouts and conditionally hiding question sub-elements), but your JavaScript can use the EM functions so that you can access questions by their Qcode instead of SGQA, and access any of the question properties listed above.&lt;br /&gt;
&lt;br /&gt;
==What are some other helpful new features enabled by EM?== &amp;lt;!--T:70--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:71--&amp;gt;&lt;br /&gt;
Regardless of whether you continue to use the Conditions Editor or manually compose Relevance Equations, you get these additional benefits:&lt;br /&gt;
#You can create more complex validation criteria&lt;br /&gt;
#*All of the advanced question attribute (like max_answers, min_num_value_n, max_num_value) can use Expressions.  So, you min/max criteria can be easily adjusted based upon prior responses, even if they are on the same page.&lt;br /&gt;
#*EM also handles all regular-expression-based validation, so you can robustly combine preg and equation-based question attributes.&lt;br /&gt;
#Easy Re-ordering (or deleting) of Questions and Groups&lt;br /&gt;
#*Prior to version 1.92, you could not re-order questions or groups if LimeSurvey thought that such-re-ordering could break conditions in which they were used.  Similarly, you could not delete questions if any other questions depended upon them.&lt;br /&gt;
#*With EM&#039;s syntax highlighting, it is easy to see and validate whether you try to use questions before they are declared.  So, we now let you re-order or delete questions and groups whenever you like.  EM will update all of the syntax highlighting to show you potential errors.&lt;br /&gt;
#*The re-order questions view has been enhanced to help with such review.  It now shows the question&#039;s relevance equation and tailoring, so you can immediately see whether any variables become pink (meaning they are used before being declared).&lt;br /&gt;
#The Question/Group Navigation Index is always available and accurate&lt;br /&gt;
#*Prior to version 1.92, these indexes were not available if there were complex conditions&lt;br /&gt;
#*With EM, we can guarantee that they are accurate.&lt;br /&gt;
#*Subjects can even jump back, to a prior question, change the answer, then jump forward (or submit)&lt;br /&gt;
#**When jumping forwards, EM will re-validate all of the intervening questions/groups.&lt;br /&gt;
#**If any questions become irrelevant, they will be NULLed in the database so that your data is internally consistent&lt;br /&gt;
#**If any questions become relevant or newly fail mandatory or validation rules, EM will stop on that page and force the user to answer those questions before jumping to their final destination.&lt;br /&gt;
#Auto-conversion of Conditions to Relevance&lt;br /&gt;
#*When you upgrade your database, all existing surveys that have conditions will have relevance equations generated for them&lt;br /&gt;
#*Whenever you import a survey, relevance equations will be created as needed&lt;br /&gt;
#*Whenever you add, delete, or modify conditions, EM will generate the appropriate relevance equation.&lt;br /&gt;
#Convenient Syntax Highlighting&lt;br /&gt;
#*When EM shows the relevance equation, it will show the Qcode, even if you entered an SGQA code, as we assume this will be easier to read.&lt;br /&gt;
#*All variables are color coded to show whether they were declared before or after the current question (or before or after the current group).  This lets you quickly detect and fix cases where you try to use variables for relevance (including array_filter), tailoring, or validation equations prior to declaring them.&lt;br /&gt;
#*In addition, if you hover your mouse over the color-coded variable, you will see the most important metadata about that question.   This includes the Group Sequence #, Question Sequence #, Qcode, Text of the question, and all available answer choices (if it is a question type with enumerated answer choices).&lt;br /&gt;
#**The list of answer choices uses this syntax:  &#039;answers&#039;:{key:val, ... }.&lt;br /&gt;
#**&#039;&#039;key&#039;&#039; has the syntax &#039;&#039;&#039;&#039;scale~code&#039;&#039;&#039;&#039; where &#039;&#039;scale&#039;&#039; is the answer scale (e.g. for dual scale), and &#039;&#039;code&#039;&#039; is the answer code.&lt;br /&gt;
#**&#039;&#039;val&#039;&#039; has the syntax &#039;&#039;&#039;&#039;value~shown&#039;&#039;&#039;&#039; where &#039;&#039;value&#039;&#039; is the assessment value (if using assessments, otherwise &#039;&#039;code&#039;&#039;)(e.g. Qcode.value), and &#039;&#039;shown&#039;&#039; is the display value as seen by the subject (e.g. Qcode.shown)&lt;br /&gt;
#**This means that many surveys can use calculations without needing assessment mode.  If you have enumerated answer options  that are unique, non-decimal, and non-negative, you can simply do calculations on the Qcode.code values.&lt;br /&gt;
#Easy review of entire survey logic and content&lt;br /&gt;
#*There is a new Show Survey Logic feature that lets you see everything about the survey (or group or question) on a single page.&lt;br /&gt;
#*It shows the Group, Question, Sub-Question, and Answer-level details for the selected scope (survey vs. group vs. question)&lt;br /&gt;
#*It also shows the relevance, sub-question-level relevance (for array_filter and array_filter_exclude), and generated validation equation (for preg and any validation rules like min/max sum/number of values), and all non-blank question attributes.&lt;br /&gt;
#*Everything is syntax-highlighted so that you can see potential syntax errors (like unbalanced parentheses or use of variables before they were declared)&lt;br /&gt;
#*The syntax-highligting supports rapid navigation and editing of the survey.&lt;br /&gt;
#**If you click on a variable name, it opens a browser window (or tab) that shows you that question and lets you edit it.&lt;br /&gt;
#**If you click on a group name, it opens a browser window (or tab) showing the group-reorder view so that you can easily move questions around.&lt;br /&gt;
#**All of the question attributes are also syntax highlighted.  This lets you set and see expressions within advanced question options (like basing the max/min number/sum of values on an expression)&lt;br /&gt;
#*The EM author used similar view (a little cleaner) to let his collaborating Epidemiologists and Institutional Review Board validate and authorize surveys with thousands of questions in highly branched and tailored structured interviews&lt;br /&gt;
&lt;br /&gt;
==How Backwards Compatible is EM with 1.91+?== &amp;lt;!--T:72--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:73--&amp;gt;&lt;br /&gt;
LimeSurvey 1.92 is fully backwards-compatible with 1.91+ with one exception/caveat:  1.92 handles less-than / greater-than comparisons against empty values differently than 1.91+.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:74--&amp;gt;&lt;br /&gt;
One of the LimeSurvey demo surveys uses a set of conditions that translates to this relevance equation:  {(age &amp;lt; 16) or (age == 20) or ... or (age == 80)}. In LimeSurvey 1.91+, (age &amp;lt; 16) is FALSE when there is no answer (the value is blank).  However, in LimeSurey 1.92, (age &amp;lt; 16) is TRUE when there is no answer, since both PHP and JavaScript treat blank as 0 in mathematical comparisons.  Thus, 1.91+ would hide that question when age was unanswered, but 1.92 would show it.  We went to great pains to prevent this, but since we needed to have the Expressions generate identical results in PHP and JavaScript, there was no way to make 1.92 treat &amp;quot;&amp;quot; &amp;lt; 16 as FALSE.  Fortunately, there is an easy work-around for this.  If you want (age &amp;lt; 16) to be FALSE, then use this expression instead: {(!is_empty(age) and age &amp;lt; 16)}.  You can use the new [[Show Logic File|Survey Logic File]] view to quickly identify and fix any such comparisons in your survey.&lt;br /&gt;
&lt;br /&gt;
=Getting Started= &amp;lt;!--T:75--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:76--&amp;gt;&lt;br /&gt;
The best way to get started with EM is to:&lt;br /&gt;
*Install the latest stable version from http://www.limesurvey.org/en/download &lt;br /&gt;
*Import and explore the [[Expression Manager Sample Surveys|sample surveys]].&lt;br /&gt;
*Explore the [[Expression Manager HowTos|use cases and HowTos]] and [[Expression Manager Examples|step-by-step examples]].&lt;br /&gt;
*Explore the EM documentation (this page)&lt;br /&gt;
*Examine the built-in EM test suite&lt;br /&gt;
**From any survey, under tools, select the EM option&lt;br /&gt;
**Available Functions lists the 70+ functions and syntax&lt;br /&gt;
**Unit Tests of Isolated Expressions&lt;br /&gt;
***shows examples of using all EM functions and operators, and the PHP and JavaScript results&lt;br /&gt;
***note there are few functions that generate different results in the PHP and JavaScript versions, so this page lets you plan your EM logic accordingly.&lt;br /&gt;
&lt;br /&gt;
=What Functionality does Expression Manager Extend/Replace? (LimeSurvey &amp;lt;= 1.91+)= &amp;lt;!--T:77--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Conditions =&amp;gt; Relevance== &amp;lt;!--T:78--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:79--&amp;gt;&lt;br /&gt;
Conditions controlled which  questions are visible.  The general syntax was &#039;&#039;SGQA operator Value&#039;&#039;, like &#039;&#039;111X2X3 == &amp;quot;Y&amp;quot;&#039;&#039;.  Conditions could be ANDed or ORed together, but mixing ANDs and ORs was difficult.  The conditions themselves were stored in a separate table, and large portion of LimeSurvey&#039;s code was devoted to managing Conditions.  Because of extensive database access, processing large numbers of conditions could cause noticable performance problems.  Furthermore, once you had conditions assigned to questions or groups, you were often not allowed to re-order or delete them.&lt;br /&gt;
&lt;br /&gt;
==Assessments =&amp;gt; Equations and  Micro-Tailoring== &amp;lt;!--T:80--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:81--&amp;gt;&lt;br /&gt;
Assessments let users create scale scores from a collection of questions.  However, they could not dynamically change on the current page, and their values were not stored to the database.&lt;br /&gt;
&lt;br /&gt;
==Replacements =&amp;gt; Micro-Tailoring== &amp;lt;!--T:82--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:83--&amp;gt;&lt;br /&gt;
Users could tailor some messages and questions based  upon prior responses.  For example, a question might be, &#039;&#039;{TOKEN:FIRSTNAME}, you said {INSERTANS:111X3X4} was your favorite sport&#039;&#039;.  However, it was not possible to do conditional tailoring (like say &amp;quot;Mr.&amp;quot; or &amp;quot;Mrs.&amp;quot; depending upon the person&#039;s gender), or conjugate verbs or decline nouns without fancy JavaScript.  Authors could implement surveys that seemed to tailor questions, but it required separate questions for each permutation, and complex conditions to decide which questions to display.&lt;br /&gt;
&lt;br /&gt;
==Validation== &amp;lt;!--T:84--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:85--&amp;gt;&lt;br /&gt;
Question could be validated with Regular expressions, or minimum/maximum values, or let an SGQA response serve as the minimum or maximum value.  However, validations could not be based upon calculations of other variables without fancy JavaScript.&lt;br /&gt;
&lt;br /&gt;
==Equations== &amp;lt;!--T:86--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:87--&amp;gt;&lt;br /&gt;
Equations were not supported without fancy JavaScript.&lt;br /&gt;
&lt;br /&gt;
==Equation Question Type== &amp;lt;!--T:88--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:89--&amp;gt;&lt;br /&gt;
Equations could not be saved to the database (e.g. the final score for an assessment) without fancy JavaScript.&lt;br /&gt;
&lt;br /&gt;
=How Will Expression Manager Replace/Extend That Functionality?= &amp;lt;!--T:90--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:91--&amp;gt;&lt;br /&gt;
The Expression Manager is a new core module within LimeSurvey that makes it much easier to support the type of complex functionality that used to require custom JavaScript.  It is also replacing the way LimeSurvey currently manages Conditions and Assessments.&lt;br /&gt;
&lt;br /&gt;
==New Terminology When Referring to Expression Manager (EM)== &amp;lt;!--T:92--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:93--&amp;gt;&lt;br /&gt;
EM &amp;quot;thinks&amp;quot; of its functionality in the following terms:&lt;br /&gt;
*&#039;&#039;&#039;Relevance-based Branching&#039;&#039;&#039; - if a question is relevant, then ask it, otherwise don&#039;t (e.g. make it invisible, and mark it as NULL in the database).  There is a new Relevance field for all Question types, and also for each Group (so you can apply a set of conditions to an entire group without having to copy the same condition to each question, and/or combine group and question-level conditional logic).&lt;br /&gt;
*&#039;&#039;&#039;Tailoring&#039;&#039;&#039; - Once you know which questions should be asked, tailoring (sometimes called &#039;&#039;piping&#039;&#039;) specifies how the question should be asked. This lets you support not only simple subsitution (like {TOKEN:FIRSTNAME}), but also conjugation of verbs and declination of nouns based upon the gender or number of your subjects.  It also lets you change the message you deliver to a subject based upon whether they answered (or how they answered) other questions.&lt;br /&gt;
*&#039;&#039;&#039;Equations&#039;&#039;&#039; - EM adds a new question type called Equation which stores the result of an Expression.  These equations results are computed and written to the database, even if you hide them on the page.  Thus, they are useful for hidden scoring calculations, navigation based upon complex equations, assessments, and reports that should be generated and easily available within the database.&lt;br /&gt;
&lt;br /&gt;
===Relevance and Cascading Relevance=== &amp;lt;!--T:94--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:95--&amp;gt;&lt;br /&gt;
Every question type now has a Relevance option which controls whether the question is displayed.  EM processes each of the Relevance Equations in the order they should appear in the survey.  If the expression is true (or missing - to support legacy surveys), the question will be displayed. If it is not relevant, then the question will be hidden, and the value will be NULLed in the database.  If there are no relevant questions in a group, the entire group will be skipped.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:96--&amp;gt;&lt;br /&gt;
Moreover, if any of the variables within an expression is irrelevant, then the expression always evaluates to false.  This enables Cascading Relevance so that you do not have to write very long Relevance equations for each question.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:97--&amp;gt;&lt;br /&gt;
Say you have 5 questions Q1-Q5, and you only want to show Q2 if Q1 was answered, and Q3 if Q2 was answered, etc.  The relevance equations might be:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:98--&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Question Code!!Relevance!!Question&lt;br /&gt;
|-&lt;br /&gt;
|Q1||1||What is your name?&lt;br /&gt;
|-&lt;br /&gt;
|Q2||Q1||{Q1}, how old are you?&lt;br /&gt;
|-&lt;br /&gt;
|Q3||Q2||So, you are {Q2} years old.  Are you married?&lt;br /&gt;
|-&lt;br /&gt;
|Q4||Q3 == &amp;quot;Y&amp;quot;||{Q1}, how long have you been married?&lt;br /&gt;
|-&lt;br /&gt;
|Q5||Q4||How many children do you have, {Q1}?&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:99--&amp;gt;&lt;br /&gt;
The relevance calculations also work in JavaScript - so you could put all the above questions on one page and it would still work as expected.  In fact, EM totally replaces how EM processes Survey vs. Group vs. Question-at-a-time survey formats.  They now all use the exactly same navigation engine so they work identically regardless of survey style.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:100--&amp;gt;&lt;br /&gt;
As long as you are on the same page, any data you entered will still be there, just hidden.  So, if you enter some information, then choose an option that makes them irrelevant, then make them relevant again, your answers will still be available.  However, as soon as you move to a different page, all irrelevant responses will be lost to integrity of the dataset.&lt;br /&gt;
&lt;br /&gt;
===Group-Level Relevance=== &amp;lt;!--T:101--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:102--&amp;gt;&lt;br /&gt;
Expression Manager also supports group-level relevance.  This makes it easier to implement looping.   Say you want to collect information about up to 10 entities (such a products or people in a household), where you first determine how many entities need follow-up (such as by asking how many people live in a household, or having people check which products they like from a long list).  After knowning how many entities need follow-up, you can use Group-level relevance like {count &amp;gt;= 1}, {count &amp;gt;=2}, ... {count &amp;gt;= 10} for each of the 10 groups of follow-up questions.  Within each group, you can have question-level conditional logic (e.g. gender or age-specific follow-up questions for each subject).  The question and group-level relevance equations are ANDed together to determine which should be shown.&lt;br /&gt;
&lt;br /&gt;
===Tailoring / Piping=== &amp;lt;!--T:103--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:104--&amp;gt;&lt;br /&gt;
Anything within curly braces is now treated as an Expression (with one exception described below).  Expressions have acccess to all of the LimeReplacementFields, all of the variables (via several aliases), all typical equation operators (mathematical, logical, and comparison), and dozens of functions (that even work dynamically on the client-side).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:105--&amp;gt;&lt;br /&gt;
Using these equations, you can do things such as:&lt;br /&gt;
#Conditionally show tailored messages to the respondants based upon prior responses&lt;br /&gt;
#Create Assessments and show Assessment results (or conditionally branch or show messages) based upon those results, all without using the Assessments module itself&lt;br /&gt;
#Conjugate verbs and decline nouns within questions, answers, and reports.&lt;br /&gt;
#Show summaries of responses before the &amp;quot;Show your answers&amp;quot; page at the end of the survey&lt;br /&gt;
&lt;br /&gt;
===Equations=== &amp;lt;!--T:106--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:107--&amp;gt;&lt;br /&gt;
There is a new question type called  Equation.  It is like a Boilerplate questions, except that it stores the value of what is displayed in the database.  So, if the Equation Question text contains an Assessment computation, that value would be stored in the database in a variable that can be displayed within public or private statistics.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:108--&amp;gt;&lt;br /&gt;
This solves a common request for storing Assessment scores within the database&lt;br /&gt;
&lt;br /&gt;
==Syntax== &amp;lt;!--T:109--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:110--&amp;gt;&lt;br /&gt;
Anything contained within curly braces is now considered an Expression (with one exception:  there must be no leading or trailing whitespace - this is needed to ensure the Expression Manager does not try to process embedded JavaScript).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:111--&amp;gt;&lt;br /&gt;
Note, it is OK for expressions to span multiple lines, as long as there is no whitespace after the opening  curly brace or before the closing curly brace.  This is especially helpful for nested if() statements like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:112--&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;{if(is_empty(PFTotals),&lt;br /&gt;
 &#039;&#039;,&lt;br /&gt;
 if(PFTotals &amp;gt;= -5 &amp;amp;&amp;amp; PFTotals &amp;lt;= -4,&lt;br /&gt;
   &#039;Very Soft&#039;,&lt;br /&gt;
   if(PFTotals &amp;gt;= -3 &amp;amp;&amp;amp; PFTotals &amp;lt;= -2,&lt;br /&gt;
     &#039;Soft&#039;,&lt;br /&gt;
     if(PFTotals == -1,&lt;br /&gt;
       &#039;Somewhat Soft&#039;,&lt;br /&gt;
       if(PFTotals == 0,&lt;br /&gt;
         &#039;Moderate&#039;,&lt;br /&gt;
         if(PFTotals == 1,&lt;br /&gt;
           &#039;Somewhat Hard&#039;,&lt;br /&gt;
           if(PFTotals &amp;gt;= 2 &amp;amp;&amp;amp; PFTotals &amp;lt;= 3,&lt;br /&gt;
             &#039;Hard&#039;,&lt;br /&gt;
             if(PFTotals &amp;gt;= 4 &amp;amp;&amp;amp; PFTotals &amp;lt;= 5,&lt;br /&gt;
               &#039;Very Hard&#039;,&lt;br /&gt;
               &#039;&#039;&lt;br /&gt;
             )&lt;br /&gt;
           )&lt;br /&gt;
         )&lt;br /&gt;
       )&lt;br /&gt;
     )&lt;br /&gt;
   )&lt;br /&gt;
 )&lt;br /&gt;
)}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:138--&amp;gt;&lt;br /&gt;
&amp;lt;div id=&amp;quot;EMsyntax&amp;quot;&amp;gt;Expression Manager supports the following syntax:&amp;lt;/div&amp;gt;&lt;br /&gt;
*All standard mathematical operators (e.g. +,-,*,/,!)&lt;br /&gt;
*All standard comparison operators (e.g. &amp;lt;,&amp;lt;=,==,!=,&amp;gt;,&amp;gt;=, plus these equivalents:  lt,le,eq,ne,gt,ge)&lt;br /&gt;
*Parentheses (so you can group sub-expressions)&lt;br /&gt;
*Conditional operators (e.g. &amp;amp;&amp;amp;,| | and these equivalents: and,or)&lt;br /&gt;
*Single and double-quoted strings (which can each embed strings with the other quote type)&lt;br /&gt;
*Comma operator (so can have a list of expressions and just return the final result)&lt;br /&gt;
*Assignment operator (=)&lt;br /&gt;
*Pre-defined variables (to refer to questions, question attributes, and responses) - e.g. all of the SGQA codes&lt;br /&gt;
*Pre-defined functions (there are already 70+, and it is easy to add more)&lt;br /&gt;
&lt;br /&gt;
=== Operators === &amp;lt;!--T:211--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:139--&amp;gt;&lt;br /&gt;
EM syntax follows normal operator precedence:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:140--&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Level!!Operator(s)!!Description&lt;br /&gt;
|-&lt;br /&gt;
|1||()||parentheses for grouping or calling functions&lt;br /&gt;
|-&lt;br /&gt;
|2||! - +||unary operators: not, negation, unary-plus&lt;br /&gt;
|-&lt;br /&gt;
|3||* /||times, divide&lt;br /&gt;
|-&lt;br /&gt;
|4||+ -||plus, minus&lt;br /&gt;
|-&lt;br /&gt;
|5||&amp;lt; &amp;lt;= &amp;gt; &amp;gt;= lt le gt ge||relative comparisons&lt;br /&gt;
|-&lt;br /&gt;
|6||== != eq ne||equality comparisons&lt;br /&gt;
|-&lt;br /&gt;
|7||and||logical AND&lt;br /&gt;
|-&lt;br /&gt;
|8||or||logical OR&lt;br /&gt;
|-&lt;br /&gt;
|9||=||assignment operator&lt;br /&gt;
|-&lt;br /&gt;
|10||,||comma operator&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:141--&amp;gt;&lt;br /&gt;
Note, for consistency between JavaScript and PHP, the plus operator (+) does addition if both operands are numeric, but does concatenation if both parts are non-numeric strings.  However, we recommend using the join() function for concatenation, as that makes your intent more clear, and avoids unexpected results if you were expecting strings but got numbers instead (or vice versa).&lt;br /&gt;
&lt;br /&gt;
===Caution about using Assignment Operator (=)=== &amp;lt;!--T:142--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:143--&amp;gt;&lt;br /&gt;
Note, you should avoid using the assignment operators unless absolutely necessary, since they may cause unexpected side-effects.  For example, if you change the value of a previous response, the cascading relevance and validation logic between that question and the current question is not re-computed, so you could end up with internally inconsistent data (e.g. questions that stay answered but should have been NULLed, or questions that are skipped but should have been answered).  In general, if you want to assign a value to a variable, you should create an Equation question type, and use an expression to set its value.  However, there are some rare times that people really need this operator, so we made it available.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:144--&amp;gt;&lt;br /&gt;
To help caution you about this operator, it is shown in red font within the syntax equations (so that you don&#039;t confuse it with &amp;quot;==&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
===Using Assignment Operator=== &amp;lt;!--T:145--&amp;gt;&lt;br /&gt;
The main reasons you may want to use assignment are:&lt;br /&gt;
*You need to set the default value for a question that does not accept defaults via equation (such as list radio, where the user interface lets you pick one of the answer options, but does not let you enter an equation).  However, be careful, as LimeSurvey will not be able to validate that your equation generates one of the allowable answers for that question.&lt;br /&gt;
*You need to forcibly change the response to a previous question based upon a later response&lt;br /&gt;
* etc...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:212--&amp;gt;&lt;br /&gt;
You can use all expression manager system for this purpose. It&#039;s better to use an [[Question_type_-_Equation|Equation question]] type to this purpose.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:213--&amp;gt;&lt;br /&gt;
Some example:&lt;br /&gt;
* Set answer to a short text question in lowercase : &amp;lt;code&amp;gt;{QCODE=strtolower(QCODE.NAOK)}&amp;lt;/code&amp;gt;&lt;br /&gt;
* Set a default answer to an array question type at start of a survey : &amp;lt;code&amp;gt;{Q1_SQ1=(is_empty(Q1_SQ1.NAOK),&amp;quot;A99&amp;quot;,Q1_SQ1.NAOK)}&amp;lt;/code&amp;gt;&lt;br /&gt;
* Set a default answer to an array texts question type at start of a survey : &amp;lt;code&amp;gt;{Q1_SQY1_SQX1 = (is_empty(Q1_SQY1_SQX1.NAOK),&amp;quot;Inserted answer&amp;quot;, Q1_SQY1_SQX1.NAOK)}&amp;lt;/code&amp;gt;&lt;br /&gt;
* Set an answer with condition : &amp;lt;code&amp;gt;{QCODE=if(YesNo=&amp;quot;Y&amp;quot;,&amp;quot;A1&amp;quot;,&amp;quot;&amp;quot;)}&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== XSS security == &amp;lt;!--T:214--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:215--&amp;gt;&lt;br /&gt;
With XSS enable, some expression manager system can not be used : &lt;br /&gt;
* starting a HTML tag in expression but ending in another expression&lt;br /&gt;
* use a complex expression in URL. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:216--&amp;gt;&lt;br /&gt;
Example and workaround&lt;br /&gt;
* &amp;lt;code&amp;gt;{if( 1 ,&amp;quot;&amp;amp;lt;strong&amp;amp;gt;&amp;quot;,&amp;quot;&amp;quot;)}information{if( 1 ,&amp;quot;&amp;amp;lt;/strong&amp;amp;gt;&amp;quot;,&amp;quot;&amp;quot;)}&amp;lt;/code&amp;gt; is broken with XSS security, here you can use &amp;lt;code&amp;gt;{if(1,&amp;quot;&amp;lt;strong&amp;amp;gt;information&amp;amp;lt;/strong&amp;amp;gt;&amp;quot;,&amp;quot;information&amp;quot;)}&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;&amp;amp;lt;a href=&amp;quot;/script.php?value={if(QCODE == &amp;quot;Y&amp;quot;,&amp;quot;yes&amp;quot;,&amp;quot;no&amp;quot;)}&amp;quot;&amp;amp;gt;next&amp;amp;lt;/a&amp;amp;gt;&amp;lt;/code&amp;gt;, here you can use an equation question because using a complete question code is OK : &amp;lt;code&amp;gt;&amp;amp;lt;a href=&amp;quot;/script.php?value={EQUATION.NAOK}&amp;quot;&amp;amp;gt;next&amp;amp;lt;/a&amp;amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Access to Variables== &amp;lt;!--T:146--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:147--&amp;gt;&lt;br /&gt;
Expression Manager provides read-only access to whichever variables we might need.  For backwards compatibility, it provides access to the following:&lt;br /&gt;
*TOKEN:xxx - the value of a TOKEN (e.g. TOKEN:FIRSTNAME, TOKEN:ATTRIBUTE_5) (Only for NOT anonymous survey).&lt;br /&gt;
*[[Adding a question#Information_from_previous_answers|INSERTANS:SGQA]] - the display value of an answer (e.g. &amp;quot;Yes&amp;quot;). For Expression Manager it&#039;s the same that using {QCODE.shown}.&lt;br /&gt;
*All [[The_template_editor#Keywords|{XXX} values used by templates]].&lt;br /&gt;
*In question text, you can use {QID} replaced by the question id and {SGQ} replaced by the SGQA of the question&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:148--&amp;gt;&lt;br /&gt;
In addition, Expression Manager lets you refer to variables by the Question Code (the &#039;title&#039; column in the questions table within the database).  This is also the variable label used when you export your data to SPSS, R, or SAS.  For example, if you have questions about name, age, and gender, you could call those variables &#039;&#039;name&#039;&#039;, &#039;&#039;age&#039;&#039;, and &#039;&#039;gender&#039;&#039; instead of &#039;&#039;12345X13X22&#039;&#039;, &#039;&#039;12345X13X23&#039;&#039;, and  &#039;&#039;12345X13X24&#039;&#039;.  This makes equations easier for everyone to read and validate the logic, plus makes it possible to shuffle questions around without having to keep track of group or question numbers.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:210--&amp;gt;&lt;br /&gt;
&amp;lt;div class=&#039;simplebox&#039;&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Important:&#039;&#039;&#039; It is only safe to refer to variables that occur in preceding pages or questions.&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:149--&amp;gt;&lt;br /&gt;
Furthermore, Expression Manager lets you access many properties of the Question:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:150--&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Syntax!!Meaning!!Example!!Example Result&lt;br /&gt;
|-&lt;br /&gt;
|Qcode||an alias for Qcode.code||{implode(&#039;,&#039;,name,gender)}||&#039;Tom&#039;,&#039;M&#039;&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.code||the selected response code for the question if it is relevant (otherwise blank), or the text value if it is not a coded question||{implode(&#039;,&#039;,name.code,gender.code)}||&#039;Tom&#039;,&#039;M&#039;&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.NAOK||same as Qcode - see discussion of NAOK||{gender.NAOK}||&#039;M&#039;&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.value||the assessment value for the question if it is relevant (otherwise blank), or the text value if it is not a coded question||{gender.value}||&#039;1&#039;&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.valueNAOK||same as Qcode.value - see discussion about NAOK||{gender.valueNAOK}||&#039;1&#039;&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.shown||the dispay value for the question||{implode(&#039;,&#039;,name.shown,gender.shown)}||&#039;Tom&#039;,&#039;Male&#039;&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.question||the text of the question||{gender.question}||&#039;What is your gender?&#039;&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.mandatory||whether the question is mandatory (Y/N)||{gender.mandatory}||&#039;N&#039;&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.qid||the internal question number (not the sequential number)||{gender.qid}||337&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.type||the question type||{gender.type}||&#039;G&#039;&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.jsName||the correct javascript name for the question, regardless whether declared on or off this page||{gender.jsName}||&#039;java1827X3X337&#039;&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.gid||the internal group number (not the sequential number)||{gender.gid}||3&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.qseq||the sequential number of the question, starting from 0||{gender.qseq}||5&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.gseq||the sequential number of the group, starting from 0||{gender.gseq}||1&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.relevanceStatus||whether the question is currently relevant (0 or 1)||{gender.relevanceStatus}||1&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.relevance||the question-level relevance equation||{gender.relevance}||&#039;!is_empty(name)&#039;&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.grelevance||the  group-level relevance equation||{gender.grelevance}||&#039;num_children &amp;gt;= 5&#039;&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.sgqa||the SGQA value for this question||{gender.sgqa}||&#039;1827X3X337&#039;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== HTML editor issue=== &amp;lt;!--T:151--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:217--&amp;gt;&lt;br /&gt;
{{Alert|This issue is fixed after 2.05 build 140803}} &lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:152--&amp;gt;&lt;br /&gt;
If you use HTML editor, some characters are replaced by HTML entities.&lt;br /&gt;
* &amp;amp; by &amp;amp;amp;amp;&lt;br /&gt;
* &amp;lt; by &amp;amp;amp;lt;&lt;br /&gt;
* &amp;gt; by &amp;amp;amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:209--&amp;gt;&lt;br /&gt;
If you use HTML editor you need to use :&lt;br /&gt;
* and for &amp;amp;&lt;br /&gt;
* lt for &amp;lt;&lt;br /&gt;
* le for &amp;lt;=&lt;br /&gt;
* gt for &amp;gt;&lt;br /&gt;
* ge for &amp;gt;=&lt;br /&gt;
&lt;br /&gt;
==Qcode Variable Naming== &amp;lt;!--T:153--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:154--&amp;gt;&lt;br /&gt;
Here are the details of how to construct a Qcode (and access some properties) by question type.  In general, Qcodes are constructed as:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:155--&amp;gt;&lt;br /&gt;
  QuestionCode . &#039;_&#039; . SubQuestionID . &#039;_&#039; . ScaleId&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:208--&amp;gt;&lt;br /&gt;
For comment and other, question code are QuestionCode_comment and QuestionCode_other&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:156--&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Type!!Description!!Code!!SubQs!!Answer Options!!Scales!!Answer Code!!Answer Shown!!Relevance&lt;br /&gt;
|-&lt;br /&gt;
|5||5 Point Choice Radio-Buttons||Q1|| ||1-5|| ||{Q1}||{Q1.shown}||{Q1==3}&lt;br /&gt;
|-&lt;br /&gt;
|B||Array (10 Point Choice) Radio-Buttons||Q2||L1-L6||1-10|| ||{Q2_L2}||{Q2_L2.shown}||{Q2_L2==7}&lt;br /&gt;
|-&lt;br /&gt;
|A||Array (5 Point Choice) Radio-Buttons||Q3||1-5||1-5|| ||{Q3_1}||{Q3_1.shown}||{Q3_1&amp;gt;=3}&lt;br /&gt;
|-&lt;br /&gt;
|1||Array (Flexible Labels) Dual Scale||Q4||sq1-sq5||0:a1-a3||1:b1-b3||{Q4_sq1_0}||{Q4_sq1_1.shown}||{Q4_sq1_1==&#039;b2&#039;}&lt;br /&gt;
|-&lt;br /&gt;
|H||Array (Flexible) - Column Format||Q5||1-5||s,m,t|| ||{Q5_1}||{Q5_1.shown}||{Q5_1==&#039;s&#039;}&lt;br /&gt;
|-&lt;br /&gt;
|F||Array (Flexible) - Row Format||Q6||F1-F5||1-5|| ||{Q6_F3}||{Q6_F3.shown}||{Q6_F3==4}&lt;br /&gt;
|-&lt;br /&gt;
|E||Array (Increase/Same/Decrease) Radio-Buttons||Q7||1-7||I,S,D|| ||{Q7_4}||{Q7_4.shown}||{Q7_4==&#039;D&#039;}&lt;br /&gt;
|-&lt;br /&gt;
|:||Array (Multi Flexi) 1 To 10||Q8||ls1,todo,ls2||min,max,avg|| ||{Q8_ls1_max}||{Q8_ls2_avg.shown}||{Q8_ls2_min==7}&lt;br /&gt;
|-&lt;br /&gt;
|;||Array (Multi Flexi) Text||Q9||hp,st,sw||1st,2nd,3rd|| ||{Q9_hp_3rd}||{Q9_hp_3rd.shown}||{Q9_hp_3rd==&#039;Peter&#039;}&lt;br /&gt;
|-&lt;br /&gt;
|C||Array (Yes/Uncertain/No) Radio-Buttons||Q10||1-5||Y,N,U|| ||{Q10_1}||{Q10_1.shown}||{Q10_3==&#039;Y&#039;}&lt;br /&gt;
|-&lt;br /&gt;
|X||Boilerplate Question||Q11|| || || || ||{Q11.shown}||&lt;br /&gt;
|-&lt;br /&gt;
|D||Date||Q12|| || || ||{Q12}||{Q12.shown}||&lt;br /&gt;
|-&lt;br /&gt;
|*||Equation||Q13|| || || ||{Q13}||{Q13.shown}||{Q13&amp;gt;5}&lt;br /&gt;
|-&lt;br /&gt;
|~124~||File Upload (records number of files uploaded)||Q14|| || || ||{Q14}|| ||{Q14&amp;gt;0}&lt;br /&gt;
|-&lt;br /&gt;
|G||Gender Drop-Down List||Q15|| ||M,F|| ||{Q15}||{Q15.shown}||{Q15==&#039;M&#039;}&lt;br /&gt;
|-&lt;br /&gt;
|U||Huge Free Text||Q16|| || || ||{Q16}||{Q16.shown}||{strlen(Q16)&amp;gt;100}&lt;br /&gt;
|-&lt;br /&gt;
|I||Language Question||Q17|| || || ||{Q17}||{Q17.shown}||{Q17==&#039;en&#039;}&lt;br /&gt;
|-&lt;br /&gt;
|!||List - Dropdown||Q18|| ||1-5|| ||{Q18}||{Q18.shown}||{Q18==3}&lt;br /&gt;
|-&lt;br /&gt;
|L||List Drop-Down/Radio-Button List||Q19|| ||A-Z|| ||{Q19}||{Q19.shown}||{Q19==&#039;X&#039;}&lt;br /&gt;
|-&lt;br /&gt;
|O||List With Comment Drop-Down/Radio-Button List + Textarea||Q20|| ||A-F|| ||{Q20},{Q20comment}||{Q20.shown}||{Q20==&#039;B&#039;}&lt;br /&gt;
|-&lt;br /&gt;
|T||Long Free Text||Q21|| || || ||{Q21}||{Q21.shown}||{strstr(Q21,&#039;hello&#039;)&amp;gt;0}&lt;br /&gt;
|-&lt;br /&gt;
|M||Multiple Choice Checkbox||Q22||A-F, other|| || ||{Q22_E}, {Q22_other}||{Q22_E.shown}, {Q22_other}||{Q22_E==&#039;Y&#039;}&lt;br /&gt;
|-&lt;br /&gt;
|P||Multiple Choice With Comments Checkbox + Text||Q23||A-F|| || ||{Q23_D}, {Q23_Dcomment}||{Q23_D.shown}||{!is_empty(Q23)}&lt;br /&gt;
|-&lt;br /&gt;
|K||Multiple Numerical Question||Q24||self,mom,dad|| || ||{Q24_self}||{Q24_self.shown}||{Q24_self&amp;gt;30}&lt;br /&gt;
|-&lt;br /&gt;
|Q||Multiple Short Text||Q25||A-F|| || ||{Q25_B}||{Q25_B.shown}||{substr(Q25_B,1,1)==&#039;Q&#039;}&lt;br /&gt;
|-&lt;br /&gt;
|N||Numerical Question Type||Q26|| || || ||{Q26}||{Q26.shown}||{Q26 &amp;gt; 30}&lt;br /&gt;
|-&lt;br /&gt;
|R||Ranking Style||Q27||1-4|| || ||{Q27_1}||{Q27_1.shown}||{Q27_1==3}&lt;br /&gt;
|-&lt;br /&gt;
|S||Short Free Text||Q28|| || || ||{Q28}||{Q28.shown}||{Q28==&#039;mine&#039;}&lt;br /&gt;
|-&lt;br /&gt;
|Y||Yes/No Radio-Buttons||Q29|| || || ||{Q29}||{Q29.shown}||{Q29==&#039;Y&#039;}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==The reserved &#039;this&#039;, &#039;self&#039;, and &#039;that&#039; variables== &amp;lt;!--T:157--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:158--&amp;gt;&lt;br /&gt;
Quite often, you want to evalute all parts of a question, such as counting how many sub-questions have been answered, or summing the scores.  Other times, you want to process just certain rows or columns of a question (such as getting the row or column sums and storing them in the database).  These reserved variables make that process relatively painless.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:159--&amp;gt;&lt;br /&gt;
The &#039;this&#039; variable is used exclusively within the &amp;quot;Whole question validation equation&amp;quot; and &amp;quot;Sub-question validation equation&amp;quot; advanced question options.  It expands to the variable names of each of the cells within those questions.  So, if you want to make sure that each entry is greater than three, you would set the &amp;quot;Sub-question validation equation&amp;quot; to (this &amp;gt; 3).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:160--&amp;gt;&lt;br /&gt;
The &#039;self&#039; and &#039;that&#039; variable are more powerful, and serve as macros which are expanded prior to processing equations.  The syntax choices are:&lt;br /&gt;
*self&lt;br /&gt;
*self.&#039;&#039;suffix&#039;&#039;&lt;br /&gt;
*self.&#039;&#039;sub-selector&#039;&#039;&lt;br /&gt;
*self.&#039;&#039;sub-selector&#039;&#039;.&#039;&#039;suffix&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:161--&amp;gt;&lt;br /&gt;
&#039;&#039;suffix&#039;&#039; is any of the normal qcode suffixes (e.g. NAOK, value, shown)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:162--&amp;gt;&lt;br /&gt;
&#039;&#039;sub-selector&#039;&#039; is one of:&lt;br /&gt;
*comments - only subquestions that are comments (e.g. from multiple choice with comment and list with comment)&lt;br /&gt;
*nocomments - only subquestions that are not comments&lt;br /&gt;
*sq_X - where X is a row or column identifier.  Only sub-questions matching pattern X are selected. Note that search is done on complete code identifier, then sq_X match and include subquestions nX, X, Xn (e.g. if you use sq_1, subquestions a1, 1a, 1, 11 or 001 was included). Put attention at dual scale question type where subquestions code are QCODE_SQCODE_1 and QCODE_SQCODE_1 and to ranking question type where subquestions code are QCODE_1,QCODE_2 ....&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:163--&amp;gt;&lt;br /&gt;
Examples:&lt;br /&gt;
*Has any part of a question been answered?  {count(self.NAOK)&amp;gt;0}&lt;br /&gt;
*What is the assessment score for this question?  {sum(self.value)}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:164--&amp;gt;&lt;br /&gt;
You can also use these to get row and column totals.  Say you have a array of numbers with rows A-E and columns 1-5.&lt;br /&gt;
*What is the grand total?  {sum(self.NAOK)}&lt;br /&gt;
*What is the total of row B?  {sum(self.sq_B.NAOK)}&lt;br /&gt;
*What is the total of column 3? {sum(self.sq_3.NAOK)}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:165--&amp;gt;&lt;br /&gt;
The &#039;that&#039; variable is like the &#039;self&#039; variable, but lets you refer to other questions.  Its syntax is:&lt;br /&gt;
*that.&#039;&#039;qname&#039;&#039;&lt;br /&gt;
*that.&#039;&#039;qname&#039;&#039;.&#039;&#039;suffix&#039;&#039;&lt;br /&gt;
*that.&#039;&#039;qname&#039;&#039;.&#039;&#039;sub-selector&#039;&#039;&lt;br /&gt;
*that.&#039;&#039;qname&#039;&#039;.&#039;&#039;sub-selector&#039;&#039;.&#039;&#039;suffix&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:166--&amp;gt;&lt;br /&gt;
&#039;&#039;qname&#039;&#039; is the question name without any sub-question extensions.  So, say you create a question &#039;q1&#039;, that is its &#039;&#039;qname&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:167--&amp;gt;&lt;br /&gt;
Examples:&lt;br /&gt;
*Has any part of question q1 been answered?  {count(that.q1.NAOK)&amp;gt;0}&lt;br /&gt;
*What is the assessment score for q2?  {sum(that.q2.NAOK)}&lt;br /&gt;
*What is the grand total of q3? {sum(that.q3.NAOK)}&lt;br /&gt;
*What is the total of row C in q4?  {sum(that.q4.sq_C.NAOK)}&lt;br /&gt;
*What is the total of column 2 in q4? {sum(that.q4.sq_2.NAOK)}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:168--&amp;gt;&lt;br /&gt;
The &#039;self&#039; and &#039;that&#039; variables can be used in any relevance,  validation, or tailoring.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:169--&amp;gt;&lt;br /&gt;
The one caveat is that when you use the [[Show Logic File|Show Logic File]] feature, it will show you the expanded value of &#039;self&#039; and &#039;that&#039;.  This lets you see the actual equation that will be generated so that you (and Expression Manager) can validate that the variables exist.  This may seem confusing since you may see quite lenghty equations.  However, if you edit the question, you will see the original equation using &#039;self&#039; and/or &#039;that&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:170--&amp;gt;&lt;br /&gt;
Also note that you should not use these variables if (a) you want to explicitly name each variable used in an equation, or (b) use variables that do not have sub-questions (e.g. single response questions).  In those cases, prefixing a variable with &#039;that&#039; is overkill, and you run the risk of getting unexpected results.&lt;br /&gt;
&lt;br /&gt;
==Usage of NAOK== &amp;lt;!--T:218--&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:219--&amp;gt;&lt;br /&gt;
NAOK --&amp;gt; &amp;quot;Not Applicable&amp;quot; (NA) is alright (OK)&lt;br /&gt;
Using NAOK, means that all or some of the variables are irrelevant (e.g. &amp;quot;Not Applicable&amp;quot; (NA) is alright (OK)). &lt;br /&gt;
&lt;br /&gt;
When you put some variable from question in any equation : if this question (or subquestion) is hidden by condition : this disable all equation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:220--&amp;gt;&lt;br /&gt;
For example : count(Q1_SQ1,Q1_SQ2,Q1_SQ3,Q1_SQ4) give always an empty string if one subquestion of Q1 is filtered.&lt;br /&gt;
To count the number of checked subquestion in such question can be count(Q1_SQ1.NAOK,Q1_SQ2.NAOK,Q1_SQ3.NAOK,Q1_SQ4.NAOK). If the sub question is hidden :Expression manager return an empty string.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:221--&amp;gt;&lt;br /&gt;
Without NAOK : if one question or one subquestion is hidden : Expression Manager return always an empty string, same to return false.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:222--&amp;gt;&lt;br /&gt;
The .shown always use the NAOK system (empty string if hidden) but if you need the code of the answer : it&#039;s always a good idea to add .NAOK after the question code. Except if you need it and know what you do.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:223--&amp;gt;&lt;br /&gt;
Another example and information is provided at [[#Overriding_Cascading_Conditions|Overriding Cascading Conditions]]&lt;br /&gt;
&lt;br /&gt;
==Access to Functions== &amp;lt;!--T:171--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:172--&amp;gt;&lt;br /&gt;
Expression Manager provides access to mathematical, string, and user-defined functions, as shown below.  It has PHP and JavaScript equivalents for these functions so that they work identically on server-side (PHP) and client-side (JavaScript).  It is easy to add new functions.&lt;br /&gt;
&lt;br /&gt;
===Implemented Functions=== &amp;lt;!--T:173--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:174--&amp;gt;&lt;br /&gt;
The following functions are currently available:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:175--&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Function!!Meaning!!Syntax&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.abs.php abs]||Absolute value||number abs(number)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.acos.php acos]||Arc cosine||number acos(number)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.addslashes.php addslashes]||Quote string with slashes||string addslashes(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.asin.php asin]||Arc sine||number asin(number)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.atan.php atan]||Arc tangent||number atan(number)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.atan2.php atan2]||Arc tangent of two variables||number atan2(number, number)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.ceil.php ceil]||Round fractions up||number ceil(number)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.checkdate.php checkdate]||Returns true(1) if it is a valid date in gregorian calendar||bool checkdate(month,day,year)&lt;br /&gt;
|-&lt;br /&gt;
|convert_value||Convert a numerical value using a inputTable and outputTable of numerical values||number convert_value(fValue, iStrict, sTranslateFromList, sTranslateToList)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.cos.php cos]||Cosine||number cos(number)&lt;br /&gt;
|-&lt;br /&gt;
|count||count the number of answered (non-blank)questions in the list||number count(arg1, arg12, ..., argN)&lt;br /&gt;
|-&lt;br /&gt;
|countif||Count the number of answered questions in the list equal the first argument||number countif(matches, arg1, arg2, ... argN)&lt;br /&gt;
|-&lt;br /&gt;
|countifop||Count the number of answered questions in the list which pass the criteria (arg op value)||number countifop(op, value, arg1, arg2, ... argN)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.date.php date]||Format a local date/time||string date(format &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;, timestamp=time()])&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.exp.php exp]||Calculates the exponent of e||number exp(number)&lt;br /&gt;
|-&lt;br /&gt;
|fixnum||Display numbers with comma as radix separator, if needed||string fixnum(number)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.floor.php floor]||Round fractions down||number floor(number)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.gmdate.php gmdate]||Format a GMT date/time||string gmdate(format &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;, timestamp=time()])&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.html-entity-decode.php html_entity_decode]||Convert all HTML entities to their applicable characters (always uses ENT_QUOTES and UTF-8)||string html_entity_decode(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.htmlentities.php htmlentities]||Convert all applicable characters to HTML entities (always uses ENT_QUOTES and UTF-8)||string htmlentities(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.htmlspecialchars.php expr_mgr_htmlspecialchars]||Convert special characters to HTML entities (always uses ENT_QUOTES and UTF-8)||string htmlspecialchars(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.htmlspecialchars-decode.php expr_mgr_htmlspecialchars_decode]||Convert special HTML entities back to characters (always uses ENT_QUOTES and UTF-8)||string htmlspecialchars_decode(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.idate.php idate]||Format a local time/date as integer||string idate(string &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;, timestamp=time()])&lt;br /&gt;
|-&lt;br /&gt;
|if||Excel-style if(test,result_if_true,result_if_false)||if(test,result_if_true,result_if_false)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.implode.php implode]||Join array elements with a string||string implode(glue,arg1,arg2,...,argN)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.intval.php intval]||Get the integer value of a variable||int intval(number &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;, base=10])&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.empty.php is_empty]||Determine whether a variable is considered to be empty||bool is_empty(var)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.is-float.php is_float]||Finds whether the type of a variable is float||bool is_float(var)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.is-int.php is_int]||Find whether the type of a variable is integer||bool is_int(var)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.is-nan.php is_nan]||Finds whether a value is not a number||bool is_nan(var)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.is-null.php is_null]||Finds whether a variable is NULL||bool is_null(var)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.is-numeric.php is_numeric]||Finds whether a variable is a number or a numeric string||bool is_numeric(var)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.is-string.php is_string]||Find whether the type of a variable is string||bool is_string(var)&lt;br /&gt;
|-&lt;br /&gt;
|join{{NewIn|2.0|b=130129}}||Join elements as a new string||join(arg1, arg2, ... argN)&lt;br /&gt;
|-&lt;br /&gt;
|list||Return comma-separated list of non-blank values||string list(arg1, arg2, ... argN)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.log.php log]|| The logarithm of number to base, if given, or the natural logarithm. ||number log(number,base=e)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.ltrim.php ltrim]||Strip whitespace (or other characters) from the beginning of a string||string ltrim(string &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;, charlist])&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.max.php max]||Find highest value||number max(arg1, arg2, ... argN)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.min.php min]||Find lowest value||number min(arg1, arg2, ... argN)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.mktime.php mktime]||Get UNIX timestamp for a date (each of the 6 arguments are optional)||number mktime([hour [, minute [, second [, month [, day [, year ]]]]]])&lt;br /&gt;
|-&lt;br /&gt;
|modulo-function||The modulo function is &#039;&#039;&#039;not supported&#039;&#039;&#039; yet. You can use the floor() function instead||floor(x/y)==(x/y)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.nl2br.php nl2br]||Inserts HTML line breaks before all newlines in a string||string nl2br(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.number-format.php number_format]||Format a number with grouped thousands||string number_format(number)&lt;br /&gt;
|-&lt;br /&gt;
|pi||Get value of pi||number pi()&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.pow.php pow]||Exponential expression||number pow(base, exp)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.quoted-printable-decode.php quoted_printable_decode]||Convert a quoted-printable string to an 8 bit string||string quoted_printable_decode(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.quoted-printable-encode.php quoted_printable_encode]||Convert a 8 bit string to a quoted-printable string||string quoted_printable_encode(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.quotemeta.php quotemeta]||Quote meta characters||string quotemeta(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.rand.php rand]||Generate a random integer, see [[Expression Manager Sample Surveys#Randomly Ask One Question Per Group|this example]]||int rand() OR int rand(min, max)&lt;br /&gt;
|-&lt;br /&gt;
|regexMatch||compare a string to a [[Using regular expressions|regular expression]]||bool regexMatch(pattern,input)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.round.php round]||Rounds a number to an optional precision||number round(val &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;, precision])&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.rtrim.php rtrim]||Strip whitespace (or other characters) from the end of a string||string rtrim(string &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;, charlist])&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.sin.php sin]||Sine||number sin(arg)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.sprintf.php sprintf]||Return a formatted string||string sprintf(format, arg1, arg2, ... argN)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.sqrt.php sqrt]||Square root||number sqrt(arg)&lt;br /&gt;
|-&lt;br /&gt;
|stddev||Calculate the Sample Standard Deviation for the list of numbers||number stddev(arg1, arg2, ... argN)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.str-pad.php str_pad]||Pad a string to a certain length with another string||string str_pad(input, pad_length &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;, pad_string])&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.str-repeat.php str_repeat]||Repeat a string||string str_repeat(input, multiplier)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.str-replace.php str_replace]||Replace all occurrences of the search string with the replacement string||string str_replace(search, replace, subject)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.strcasecmp.php strcasecmp]||Binary safe case-insensitive string comparison||int strcasecmp(str1, str2)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.strcmp.php strcmp]||Binary safe string comparison||int strcmp(str1, str2)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.strip-tags.php strip_tags]||Strip HTML and PHP tags from a string||string strip_tags(str, allowable_tags)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.stripos.php stripos]||Find position of first occurrence of a case-insensitive unicode string (starting by 0, return false if not found)|||int stripos(haystack, needle &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;, offset=0])&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.stripslashes.php stripslashes]||Un-quotes a quoted string||string stripslashes(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.stristr.php stristr]||Case-insensitive strstr||string stristr(haystack, needle &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;, before_needle=false])&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.strlen.php strlen]||Get string length||int strlen(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.strpos.php strpos]||Find position of first occurrence of an unicode string (starting by 0, return false if not found)||int strpos(haystack, needle &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt; offset=0])&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.strrev.php strrev]||Reverse a string||string strrev(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.strstr.php strstr]||Find first occurrence of a string||string strstr(haystack, needle&amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;, before_needle=false])&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.strtolower.php strtolower]||Make a string lowercase||string strtolower(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.strtotime.php strtotime]||Parse about any English textual datetime description into a Unix timestamp||int strtotime(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.strtoupper.php strtoupper]||Make a string uppercase||string strtoupper(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.substr.php substr]||Return part of an unicode string||string substr(string, start &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;, length])&lt;br /&gt;
|-&lt;br /&gt;
|sum||Calculate the sum of values in an array||number sum(arg1, arg2, ... argN)&lt;br /&gt;
|-&lt;br /&gt;
|sumifop||Sum the values of answered questions in the list which pass the criteria (arg op value)||number sumifop(op, value, arg1, arg2, ... argN)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.tan.php tan]||Tangent||number tan(arg)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.time.php time]||Return current UNIX timestamp||number time()&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.trim.php trim]||Strip whitespace (or other characters) from the beginning and end of a string||string trim(string &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;, charlist])&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.ucwords.php ucwords]||Uppercase the first character of each word in a string||string ucwords(string)&lt;br /&gt;
|-&lt;br /&gt;
|unique||Returns true if all non-empty responses are unique||boolean unique(arg1, ..., argN)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Functions that are Planned or Being Considered=== &amp;lt;!--T:176--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:177--&amp;gt;&lt;br /&gt;
Other functions that are planned (or being considered) but which are not implemented yet include the following.  Some of these are for backwards compatability with another survey tool.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:178--&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Syntax!!Meaning!!Comments&lt;br /&gt;
|-&lt;br /&gt;
|e()||returns the value of e||&lt;br /&gt;
|-&lt;br /&gt;
|formatDate(X,PAT)||return the string value of date X formatted according to Java data format pattern PAT||&lt;br /&gt;
|-&lt;br /&gt;
|formatNumber(X,PAT)||return the string value of number X formatted according to Java number format pattern PAT||&lt;br /&gt;
|-&lt;br /&gt;
|getAnsOption(X)||returns the text corresponding to the selected option for answer X||this is the same as X.shown&lt;br /&gt;
|-&lt;br /&gt;
|getAnsOption(X,Y)||returns the text corresponding to the option at index Y of node X||&lt;br /&gt;
|-&lt;br /&gt;
|getRelevance(X)||returns the relevance equation for question X||&lt;br /&gt;
|-&lt;br /&gt;
|getStartTime()||returns the date corresponding to the system time when the interview was started||&lt;br /&gt;
|-&lt;br /&gt;
|getType(X)||returns the string name of the datatype - e.g. *NA* if isNA()||&lt;br /&gt;
|-&lt;br /&gt;
|gotoFirst()||jumps to the first relevant set of questions - this violates the normal flow of the system||&lt;br /&gt;
|-&lt;br /&gt;
|gotoNext()||jumps to the next set of relevant questions - this violates the normal flow of the system||&lt;br /&gt;
|-&lt;br /&gt;
|gotoPrevious()||jumps to the previous set of relevant questions - this violates the normal flow of the system||&lt;br /&gt;
|-&lt;br /&gt;
|isAsked(X)||returns true if the answer is neither *NA*, *INVALID*, nor *UNASKED*||&lt;br /&gt;
|-&lt;br /&gt;
|isInvalid(X)||returns true if the answer is of type *INVALID*||&lt;br /&gt;
|-&lt;br /&gt;
|isNA(X)||returns true if the answer is of type *NA*||&lt;br /&gt;
|-&lt;br /&gt;
|isNotUnderstood(X)||returns true if the answer if of type *HUH*||&lt;br /&gt;
|-&lt;br /&gt;
|isRefused(X)||returns true if the answer is of type *REFUSED*||&lt;br /&gt;
|-&lt;br /&gt;
|isSpecial(X)||returns true if the answer is of type *UNASKED*, *NA*, *REFUSED*, *INVALID*, *UNKNOWN*, or *HUH*||&lt;br /&gt;
|-&lt;br /&gt;
|isUnknown(X)||returns true if the answer is of type *UNKNOWN*||&lt;br /&gt;
|-&lt;br /&gt;
|jumpTo(X)||jump to the group containing the named question -- this violates the normal flow of the system||&lt;br /&gt;
|-&lt;br /&gt;
|jumpToFirstUnasked()||jump to the first unasked question &amp;lt;strike&amp;gt; thus bypassing previous answered questions &amp;lt;/strike&amp;gt; this violates the normal flow of the system||&lt;br /&gt;
|-&lt;br /&gt;
|lastIndexOf(X,Y)||returns the last index (base 0) of string Y in string X. Returns -1 if Y is not contained within X||&lt;br /&gt;
|-&lt;br /&gt;
|list(X,...)||a string containing a comma separated list of the positive values with &amp;quot;and&amp;quot; separating the last two||&lt;br /&gt;
|-&lt;br /&gt;
|mean(X,...)||returns the mean of a list of values||&lt;br /&gt;
|-&lt;br /&gt;
|numAnsOptions(X)||returns the number of answer options that question X has||&lt;br /&gt;
|-&lt;br /&gt;
|orlist(X,...)||a string containing a comma separated list of the positive values, with &amp;quot;or&amp;quot; separting the last two||&lt;br /&gt;
|-&lt;br /&gt;
|parseDate(X,PAT)||returns the date value of string X parsed with Java date format pattern PAT||&lt;br /&gt;
|-&lt;br /&gt;
|parseNumber(X,PAT)||returns the numerical value of string X parsed with Java number format pattern PAT||&lt;br /&gt;
|-&lt;br /&gt;
|showAllResponsesExcept( questionList,attributeList,attributeTitleList)||questionList = pipe-delimited list of question identifiers; attributeList = pipe-delimited list of attributes (like question#, title, text, type - so you can decide what to show); attributeTitleList = pipe-delimited list of table headers, so can internationalize the report.||&lt;br /&gt;
|-&lt;br /&gt;
|showTheseResponses( questionList,attributeList,attributeTitleList)||questionList = pipe-delimited list of question identifiers; attributeList = pipe-delimited list of attributes (like question#, title, text, type - so you can decide what to show); attributeTitleList = pipe-delimited list of table headers, so can internationalize the report.|| &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Expression Manager Knows Which Variables are Local== &amp;lt;!--T:179--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:180--&amp;gt;&lt;br /&gt;
In order to properly build the JavaScript for page, Expression Manager needs to know which variables are set on the page, and what their JavaScript ID is (e.g. for document.getElementById(x)).  It also must know which variables are set on other pages (so that it can ensure that the needed &amp;lt;input type=&#039;hidden&#039; value=&#039;x&#039;&amp;gt; fields are present and populated).&lt;br /&gt;
&lt;br /&gt;
==Cascading Conditions== &amp;lt;!--T:181--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:182--&amp;gt;&lt;br /&gt;
If any of the variables are irrelevant, the whole equation will be irrelevant (false).  For example, in the following table, N/A means that one of the variables was not relevant&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:183--&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Operator!!Example!!a!!b!!Result&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;+ (unary)&amp;lt;/nowiki&amp;gt;||&amp;lt;nowiki&amp;gt;+a&amp;lt;/nowiki&amp;gt;||N/A|| ||false&lt;br /&gt;
|-&lt;br /&gt;
|- (unary)||-a||N/A|| ||false&lt;br /&gt;
|-&lt;br /&gt;
|!||!a||N/A|| ||false&lt;br /&gt;
|-&lt;br /&gt;
|== (or eq)||a == b||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|== (or eq)||a == b||N/A||0||false&lt;br /&gt;
|-&lt;br /&gt;
|== (or eq)||a == b||N/A||N/A||false&lt;br /&gt;
|-&lt;br /&gt;
|!= (or ne)||a != b||N/A||5|| false&lt;br /&gt;
|-&lt;br /&gt;
|!= (or ne)||a != b||N/A||N/A|| false&lt;br /&gt;
|-&lt;br /&gt;
|!= (or ne)||a != b||N/A||0||false&lt;br /&gt;
|-&lt;br /&gt;
|&amp;gt; (or gt)||a &amp;gt; b||N/A||5|| false&lt;br /&gt;
|-&lt;br /&gt;
|&amp;gt;= (or ge)||a &amp;gt;= b||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt; (or lt)||a &amp;lt; b||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;= (or le)||a &amp;lt;= b||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|and||a and b||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|and||a and b||N/A||N/A||false&lt;br /&gt;
|-&lt;br /&gt;
|or||a or b||N/A||N/A||false&lt;br /&gt;
|-&lt;br /&gt;
|or||a or b||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;+&amp;lt;/nowiki&amp;gt;||a + b||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|-||a - b||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|*||a * b||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|/||a / b||5||N/A||false&lt;br /&gt;
|-&lt;br /&gt;
|()||(a)||N/A|| ||false&lt;br /&gt;
|-&lt;br /&gt;
|(exp)||(a &amp;amp;&amp;amp; b)||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|(exp) op (exp)||(b + b) &amp;gt; (a &amp;amp;&amp;amp; b)||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|function||sum(a,b,b)||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|function||max(a,b)||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|function||min(a,b)||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|function||implode(&#039;, &#039;,a,b,a,b)||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|function||if(a,a,b)||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|function||is_empty(a)||N/A|| ||false&lt;br /&gt;
|-&lt;br /&gt;
|function||is_empty(a)||0 (or blank)|| ||true&lt;br /&gt;
|-&lt;br /&gt;
|function||!is_empty(a)||N/A|| ||false&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Overriding Cascading Conditions=== &amp;lt;!--T:184--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:185--&amp;gt;&lt;br /&gt;
Say you want to show a running total of all relevant answers.  You might try to use the equation {sum(q1,q2,q3,...,qN)}.  However, this gets translated internally to LEMif(LEManyNA(&#039;q1&#039;,&#039;q2&#039;,&#039;q3&#039;,...,&#039;qN&#039;),&#039;&#039;,sum(LEMval(&#039;q1&#039;),LEMval(&#039;q2&#039;),LEMval(&#039;q3&#039;),...,LEMval(&#039;qN&#039;))).  So, if any of the values q1-qN are irrelevant, the equation will always return false.  In this case, the sum() will show 0 until all questions are answered.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:186--&amp;gt;&lt;br /&gt;
To get around this, each variable can have a &amp;quot;.NAOK&amp;quot; suffix (meaning that Not Applicable is OK) added to it.  In such cases, the following behavior occurs.  Say you have a variable q1.NAOK&lt;br /&gt;
#q1 is not added to the LEManyNA() clause&lt;br /&gt;
#LEMval(&#039;q1&#039;) will  continue to check whether the response is relevant, and will return &amp;lt;nowiki&amp;gt;&#039;&#039;&amp;lt;/nowiki&amp;gt; if it is not (so individual irrelevant responses will be ignored, but they will not void the entire expression).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:187--&amp;gt;&lt;br /&gt;
So, the solution to the running total problem is to use the equation sum(q1.NAOK,q2.NAOK,q3.NAOK,...,qN.NAOK).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:188--&amp;gt;&lt;br /&gt;
The use of the .NAOK suffix also lets authors design surveys that have several possible paths but then converge on common paths later.  For example, say subjects answer a survey in a way that is outside the normal range of responses.  The author could alert the subjects that they may not get valid results, and ask them whether they really want to  continue with the survey.  If they say Yes, then the rest of the questions will be shown.  The condition for the &amp;quot;rest of the questions&amp;quot; would check whether the initial responses were answered within the normal range OR whether the subject said Yes to the question that is only relevant if they answered outside the normal range.&lt;br /&gt;
&lt;br /&gt;
==How does Expression Manager Support Conditional Micro-Tailoring?== &amp;lt;!--T:189--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:190--&amp;gt;&lt;br /&gt;
Here is an example of micro-tailoring (where Question Type==&#039;expr&#039; means an Equation):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:191--&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Question Code!!Relevance!!Question Type!!Question&lt;br /&gt;
|-&lt;br /&gt;
|name||1||text||What is your name?&lt;br /&gt;
|-&lt;br /&gt;
|age||1||text||How old are you?&lt;br /&gt;
|-&lt;br /&gt;
|badage||!is_empty(age)||expr||{(age&amp;lt;16) or (age&amp;gt;80)}&lt;br /&gt;
|-&lt;br /&gt;
|agestop||badage||message||Sorry, {name}, you are too {if( (age&amp;lt;16),&#039;young&#039;,if( (age&amp;gt;80),&#039;old&#039;,&#039;middle-aged&#039;) ) } for this test.&lt;br /&gt;
|-&lt;br /&gt;
|kids||!badage||yesno||Do you have children?&lt;br /&gt;
|-&lt;br /&gt;
|parents||1||expr||{!badage &amp;amp;&amp;amp; kids==&#039;Y&#039;}&lt;br /&gt;
|-&lt;br /&gt;
|numKids||parents||text||How many children do you have?&lt;br /&gt;
|-&lt;br /&gt;
|kid1||parents &amp;amp;&amp;amp; numKids &amp;gt;= 1||text||How old is your first child?&lt;br /&gt;
|-&lt;br /&gt;
|kid2||parents &amp;amp;&amp;amp; numKids &amp;gt;= 2||text||How old is your second child?&lt;br /&gt;
|-&lt;br /&gt;
|kid3||parents &amp;amp;&amp;amp; numKids &amp;gt;= 3||text||How old is your third child?&lt;br /&gt;
|-&lt;br /&gt;
|kid4||parents &amp;amp;&amp;amp; numKids &amp;gt;= 4||text||How old is your fourth child?&lt;br /&gt;
|-&lt;br /&gt;
|kid5||parents &amp;amp;&amp;amp; numKids &amp;gt;= 5||text||How old is your fifth child?&lt;br /&gt;
|-&lt;br /&gt;
|sumage||1||expr||{sum(kid1.NAOK,kid2.NAOK,kid3.NAOK,kid4.NAOK,kid5.NAOK)}&lt;br /&gt;
|-&lt;br /&gt;
|report||parents||yesno||{name}, you said you are {age} and that you have {numKids}.  The sum of ages of your first {min(numKids,5)} kids is {sumage}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:192--&amp;gt;&lt;br /&gt;
All of these questions can be on a single page (e.g. in the same group), and only the relevant questions will display.  Moreover, as you enter the ages of children, the sum() expression in the last question will dynamically update on the page.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:193--&amp;gt;&lt;br /&gt;
Expression Manager provides this functionality by surrounding each expression with a named &amp;lt;span&amp;gt; element.  Every time a value changes, it recomputes the expression that should appear in that &amp;lt;span&amp;gt; element and regenerates the display.  You can have dozens, or even hundreds, of such tailored expressions on the same page, and the page will re-display all of them in a single screen refresh.&lt;br /&gt;
&lt;br /&gt;
==Mapping of LimeSurvey 1.91+ to Expression Manager Functionality== &amp;lt;!--T:194--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:195--&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Old Feature!!New Feature!!Comments&lt;br /&gt;
|-&lt;br /&gt;
|Conditions||Relevance||You can use very complex conditional equations, and access a broader range of variables&lt;br /&gt;
|-&lt;br /&gt;
|Assessments||Equation||Any assessment scores can be re-structured into an Equation. This both ensures that the score is written to the database, and also lets you see dynamic changes to the score value on the current page&lt;br /&gt;
|-&lt;br /&gt;
|Replacements||Expression Manager||The core engine takes the input string and treats everything within curly braces as an Expression - so it handles all historical replacements types.  To avoid messing up embedded JavaScript, Expression Manager only processes content between curly braces as long as (a)  there is no leading or trailing whitespace within the curly braces - e.g. {expr} is an expression, but { expr}, {expr }, and { expr } are not expressions.  Furthermore, Expression Manager does not process content within its own strings (e.g. {list(&#039;hi&#039;,&#039;there {braces}&#039;)} generates &amp;quot;hi there {braces}&amp;quot;).  It also ignores escaped curly braces (e.g. \{this is not an expression\})&lt;br /&gt;
|-&lt;br /&gt;
|Validation||Expression Manager||The plan is to take the current min/max Question Attributes and have Expression Manager process them.  That way the min/max values can be expressions themselves&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Syntax Highlighting= &amp;lt;!--T:196--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:197--&amp;gt;&lt;br /&gt;
To help with entering and validating expressions, EM provides syntax highlighting with the following features:&lt;br /&gt;
&lt;br /&gt;
==Types and Meanings of Syntax Highlighting== &amp;lt;!--T:198--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:199--&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Color!!Sample!!Meaning!!Tooltip!!Comments&lt;br /&gt;
|-&lt;br /&gt;
|tan background||style=&#039;background-color: #eee8aa&#039;|Sample||the whole equation||none||Anything within curly braces that is recognized as an equation (e.g. there is no leading or trailing whitepace) will be color-coded with a tan background to help distinguish it from surrounding text&lt;br /&gt;
|-&lt;br /&gt;
|bold red text||style=&#039;color:#ff0000; background-color:#eee8aa&#039;|&#039;&#039;&#039;Sample&#039;&#039;&#039;||An error||Some explanation on error||Can be an unknow variable or an error in function, .... Survey can be totally broken, this don&#039;t show to public user.&lt;br /&gt;
|-&lt;br /&gt;
|blue text||style=&#039;color:#0000ff; background-color:#eee8aa&#039;|Sample||function name||meaning and allowable syntax||function names, or things that should be functions since they are followed by an opening parenthesis, are presented in bold blue text.  Tooltips show the meaning and allowable syntax for the function.&lt;br /&gt;
|-&lt;br /&gt;
|grey text||style=&#039;color:#808080; background-color:#eee8aa&#039;|Sample||string||none||single and double-quoted strings are shown in grey text&lt;br /&gt;
|-&lt;br /&gt;
|cyan text||style=&#039;color:#4169e1; background-color:#eee8aa&#039;|Sample||variable set on the same page,||&amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;name or SGQA code]: question; value; answerList showing codes for each value||Any variable that is set on the same page to the current question is shown in cyan text, showning it can be updated in javascript.  The tooltip shows its name (if you used INSERTANS:xxx) or SGQA code (if you used the new naming system), the actual question, and its current value (or blank if not set).  If the question type expects responses from an enumerated value set, the mapping of the codes to display values is show.&lt;br /&gt;
|-&lt;br /&gt;
|green text||style=&#039;color:#008000; background-color:#eee8aa&#039;|Sample||variable set on a prior page||&amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;name or SGQA code]: question; value; answerList showing codes for each value||Any variable that is set on a prior page is shown in bold green text.  The tooltip shows its name (if you used INSERTANS:xxx) or SGQA code (if you used the new naming system), the actual question, and its current value (or blank if not set).  If the question type expects responses from an enumerated value set, the mapping of the codes to display values is show.&lt;br /&gt;
|-&lt;br /&gt;
|bold pink text||style=&#039;color:#9370db; background-color:#eee8aa&#039;|Sample||variable set on a later page &amp;lt;sup&amp;gt;in general : empty at survey start, but can be filled with index or move previous&amp;lt;/sup&amp;gt;||&amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;name or SGQA code]: question; value; answerList showing codes for each value||Any variable that is set on a prior page is shown in bold pink text.  These are erorrs since the variable is  being used before it is declareed.  The tooltip shows its name (if you used INSERTANS:xxx) or SGQA code (if you used the new naming system), the actual question, and its current value (or blank if not set).  If the question type expects responses from an enumerated value set, the mapping of the codes to display values is show.&lt;br /&gt;
|-&lt;br /&gt;
|bold tan text||style=&#039;color:#a0522d; background-color:#eee8aa&#039;|Sample||a lime replacement value||the value||Lime Replacement Strings (like {TOKEN:xxx}, {PRIVACY_MESSAGE}) are shown in bold tan text.  &lt;br /&gt;
|-&lt;br /&gt;
|red text||style=&#039;color:#ff4500; background-color:#eee8aa&#039;|Sample||assignment operator (=) ||warning message||If you use one of the assignment operator (=) that operator will be displayed in red text.  This is meant to help prevent accidental re-assignment of values when you really meant to check whether a == b instead of  setting the value of a = b.&lt;br /&gt;
|-&lt;br /&gt;
|normal black text||style=&#039;color:black; background-color:#eee8aa&#039;|Sample||punctuation||none||All other punctuation within the expression is shown as normal black text.&lt;br /&gt;
|-&lt;br /&gt;
|red-boxed text||a bold red line surrounds the error||syntax error||description of the error||Any detected syntax errors are shown by surrounding the error with a red box.  The tooltip shows the error.  Examples include unmatched parentheses, use of undefined functions, passing the wrong number of arguments to functions, poorly structured expressions (e.g. missing operators between variables), trying to assign a new value to a read-only variable, trying to assign values to non-variables, or using unsupported syntax.  Note that the syntax error dectection system may only report one error in an expression even if there are multiple errors; however, if any errors are detected, at least one error will be shown.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Additional Reading= &amp;lt;!--T:202--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==[[Expression Manager Sample Surveys|Expression Manager Sample Surveys]]== &amp;lt;!--T:203--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==[[Expression Manager HowTos|Use Cases and HowTos]]== &amp;lt;!--T:204--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==[[Expression Manager Examples|Step-by-Step Examples]].== &amp;lt;!--T:205--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==[[Expression Manager for developers|Reference for Developers]]== &amp;lt;!--T:206--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==[[Expression Manager Roadmap|RoadMap/Status/ToDo List]]== &amp;lt;!--T:207--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/translate&amp;gt;&lt;/div&gt;</summary>
		<author><name>LimeAJ</name></author>
	</entry>
	<entry>
		<id>https://www.limesurvey.org/manual/index.php?title=Expression_Manager&amp;diff=73880</id>
		<title>Expression Manager</title>
		<link rel="alternate" type="text/html" href="https://www.limesurvey.org/manual/index.php?title=Expression_Manager&amp;diff=73880"/>
		<updated>2017-07-04T17:22:48Z</updated>

		<summary type="html">&lt;p&gt;LimeAJ: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;languages /&amp;gt; &amp;lt;translate&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:1--&amp;gt;&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:2--&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;simplebox&amp;quot;&amp;gt; Note: This feature is only available in LimeSurvey 1.92 or later. &amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Quick Start Tutorial= &amp;lt;!--T:3--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Overview== &amp;lt;!--T:4--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:5--&amp;gt;&lt;br /&gt;
When customizing your surveys, you typically need a way to specify the following:&lt;br /&gt;
#&#039;&#039;&#039;Navigation/Branching&#039;&#039;&#039; - letting a subject&#039;s answers change the order in which questions are asked&lt;br /&gt;
#&#039;&#039;&#039;Tailoring/Piping&#039;&#039;&#039; - how to phrase the question (such as referring to prior answers, or conjugating sentences based upon the number or gender of your subjects), or how to generate custom reports (like assessment scores or tailored advice).&lt;br /&gt;
#&#039;&#039;&#039;Validation&#039;&#039;&#039; - ensuring that answers pass certain criteria, like min and max values, or matching an input pattern&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:6--&amp;gt;&lt;br /&gt;
Expression Manager (EM) provides an intuitive way to specifying the logic for each of those features.  Nearly anything that you can write as a standard mathematical equation is a valid expression, even if you are calling functions.  EM currently provides access to 70 functions, and can be easily extended to support more.  It also lets you access your variables using human-readable variable names (rather than SGQA names).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:7--&amp;gt;&lt;br /&gt;
The following sections show the main places where Expression Manager is used&lt;br /&gt;
&lt;br /&gt;
==Relevance (Controlling Navigation/Branching)== &amp;lt;!--T:8--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:9--&amp;gt;&lt;br /&gt;
Some surveys use &amp;quot;Goto Logic&amp;quot;, such that if you answer Question 1 with option C, then jump to Question 5. This approach is very limiting, since is hard to validate, and easily breaks if you have to re-order questions.  EM uses a Boolean relevance equation to specify all of the conditions under which a question might be valid.  If the question is relevant, then the question is asked, otherwise it is Not Applicable, and the value NULL is stored in the database.  This is similar to what can be done via the Conditions editor, but EM lets you easily specify much more complex and powerful criteria (and lets you use the variable name rather than SGQA naming).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:10--&amp;gt;&lt;br /&gt;
This image shows one way to review the relevance logic for a survey.  It computes Body Mass Index.  The relevance equation is shown in square bracket right after the variable name (which is in green).  So, the relevance of weight, weight_units, height and height_units are all 1, meaning that those questions are always asked.  However, the relevance for BMI is {!is_empty(height) and !is_empty(weight)}, which means that BMI will only be computed if the subject enters a value for both height and weight (thereby avoiding the risk of a divide by zero error).  Also, the Report question is only shown if the subject answers all four main questions (height, height_units, weight, weight_units).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:11--&amp;gt;&lt;br /&gt;
[[File:tutorial1.jpg]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:12--&amp;gt;&lt;br /&gt;
Relevance is shown and editable in the following places:&lt;br /&gt;
&lt;br /&gt;
===Viewing / Editing Question-Level Relevance=== &amp;lt;!--T:13--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:14--&amp;gt;&lt;br /&gt;
This equation computes the Body Mass Index (BMI).  It is only asked if the person first enters their height and weight.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:15--&amp;gt;&lt;br /&gt;
[[File:tutorial2.jpg]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:16--&amp;gt;&lt;br /&gt;
This is the edit screen for the BMI question.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:17--&amp;gt;&lt;br /&gt;
[[File:tutorial3.jpg]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:18--&amp;gt;&lt;br /&gt;
Note that you do not use the curly braces when you enter a Relevance Equation.&lt;br /&gt;
&lt;br /&gt;
===Viewing / Editing Group-Level Relevance=== &amp;lt;!--T:19--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:20--&amp;gt;&lt;br /&gt;
This is a sample census survey.  The first page asks how many people live with you and stores that in the &amp;quot;cohabs&amp;quot; variable.  This page is only shown if you have more than one cohabitant (so it is shown for the second person cohabitating with you), and also only shows if you specified how Person One is related to you (p1_rel).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:21--&amp;gt;&lt;br /&gt;
[[File:tutorial4.jpg]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:22--&amp;gt;&lt;br /&gt;
As you can see, the group also has question-level relevance criteria, such that each question only appears once you have answered the question before it (e.g. {!is_empty(p1_sex)}).  EM combines the Group and Question-level relevance for you.  Questions in a group are only asked  if the group as a whole is relevant.  Then, only the subset of questions within the group that are relevant are asked.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:23--&amp;gt;&lt;br /&gt;
Here is the screen for editing the group-level relevance for that question:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:24--&amp;gt;&lt;br /&gt;
[[File:tutorial5.jpg]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:25--&amp;gt;&lt;br /&gt;
Note that you do not use the curly braces when you enter a Relevance Equation.&lt;br /&gt;
&lt;br /&gt;
==Tailoring/Piping== &amp;lt;!--T:26--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:27--&amp;gt;&lt;br /&gt;
EM lets you easily do simple and complex conditional tailoring of your questions.  Sometimes you just need simple substitution, like saying, &amp;quot;You said you purchased &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;Product].  What did you like best about it?&amp;quot;.  Sometimes you need conditional substitution like &amp;quot;&amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;Mr./Mrs.] &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;LastName], would you be willing to complete our survey?&amp;quot;.  In this case,  you want to use Mr. or Mrs. based upon the person&#039;s gender.  Other times you need even more complex substitution (such as based upon a mathematical computation).  EM supports each of these types of tailoring/piping.&lt;br /&gt;
&lt;br /&gt;
===Conditional Equations=== &amp;lt;!--T:28--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:29--&amp;gt;&lt;br /&gt;
The Body Mass Index example shows the ability to compute a person&#039;s BMI, even while letting them enter their height in weight in metric or non-metric units.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:30--&amp;gt;&lt;br /&gt;
[[File:tailoring7.jpg]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:31--&amp;gt;&lt;br /&gt;
Here weight_kg is {if(weight_units == &#039;kg&#039;, weight, weight * .453592)}.  This if() function means that if the subject entered the weight using kilograms, use that value, otherwise multiple the entered value (which was in pounds) by .453592 to convert it to kilograms.  The height_m variable uses a similar approach to compute the person&#039;s height in meters, even if he entered his height in inches.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:32--&amp;gt;&lt;br /&gt;
BMI computes the weight formula as {weight_kg / (height_m * height_m)}.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:33--&amp;gt;&lt;br /&gt;
Lastly, the report conditionally tailors the message for the subject, telling him what he entered. (&amp;quot;You said you are 2 meters tall and weight 70 kg.&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:34--&amp;gt;&lt;br /&gt;
Although not well shown in the above image, weight_status uses nested if() statements to categorize the person as underweight to severely obese.  You can see its equation in the Show Logic View&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:35--&amp;gt;&lt;br /&gt;
[[File:tailoring8.jpg]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:36--&amp;gt;&lt;br /&gt;
From the edit window for this question, you can see two things:&lt;br /&gt;
#Tailoring must surround expressions with Curly Braces&lt;br /&gt;
#Expressions can span multiple lines if, as in this case, you want to make it easier to read the nested conditional logic.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:37--&amp;gt;&lt;br /&gt;
[[File:tailoring9.jpg]]&lt;br /&gt;
&lt;br /&gt;
===Tailored Questions, Answers, and Reports=== &amp;lt;!--T:38--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:39--&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;simplebox&amp;quot;&amp;gt;Note: Dynamic tailoring may not work if answer options are made available in select boxes on the same question page. This results from the fact that tailoring inserts a &amp;lt;nowiki&amp;gt;&amp;lt;span&amp;gt;&amp;lt;/nowiki&amp;gt; tag which is not valid inside select options.&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:40--&amp;gt;&lt;br /&gt;
This example shows the BMI report.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:41--&amp;gt;&lt;br /&gt;
[[File:tailoring10.jpg]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:42--&amp;gt;&lt;br /&gt;
Here is the edit window for the same question.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:43--&amp;gt;&lt;br /&gt;
[[File:tailoring11.jpg]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:44--&amp;gt;&lt;br /&gt;
As you can see, anything in curly braces is treated as an expression, so is syntax-highlighted (color coded) in the prior image.  If you had any typos (such as misspelled or undefined variable names or functions), EM would show an error, such as this, showing that height_unit is an undefined variable name (it is actually height_units), and rnd() is an undefined function (the proper function name is round()).  In both cases, the errors are surrounded by a red box to make it easier to spot and fix them.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:45--&amp;gt;&lt;br /&gt;
[[File:tailoring12.jpg]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:46--&amp;gt;&lt;br /&gt;
You can also see that you can quickly create complex reports, such as a table of entered values or tailored advice.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:47--&amp;gt;&lt;br /&gt;
Please remember that all tailoring must surround expressions with Curly Braces, so that LimeSurvey knows which parts of the question are free text and which should be parsed through Expression Manager.&lt;br /&gt;
&lt;br /&gt;
==Validation== &amp;lt;!--T:48--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:49--&amp;gt;&lt;br /&gt;
EM controls how most of the advanced question options work.  These control aspects like min/max numbers of answers; min/max individual values; min/max sum values; and checking that entered values match specified string patterns.  You continue to enter those advanced question options as usual.  However, now any value in one of those fields is considered an expression, so you can have min/max criteria with complex conditional relationships to other questions.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:50--&amp;gt;&lt;br /&gt;
In all of these cases, since the advanced question option is always considered an expression, you do not use curly braces when specifying it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:51--&amp;gt;&lt;br /&gt;
The [[Expression Manager Sample Surveys|Sample Surveys]] pages shows many working examples of using expressions for validations.&lt;br /&gt;
&lt;br /&gt;
=Introduction= &amp;lt;!--T:52--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:53--&amp;gt;&lt;br /&gt;
LimeSurvey uses the new Expression Manager (EM) module which will let LimeSurvey support more complex branching, assessments, validation, and tailoring.  It will replace how LimeSurvey manages Replacements, Conditions, and Assessments on the back-end.  It will also speed up processing considerably since it eliminates most run-time database reads.  EM was developed by Dr. Thomas White (TMSWhite).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:54--&amp;gt;&lt;br /&gt;
This wiki page is the definitive reference for Expression Manager syntax and functionality.&lt;br /&gt;
&lt;br /&gt;
==Key Definitions== &amp;lt;!--T:55--&amp;gt;&lt;br /&gt;
#&#039;&#039;&#039;Expression&#039;&#039;&#039;:  Anything surrounded by curly braces&lt;br /&gt;
#*As long as there is no white space immediately after the opening brace or before the closing curly brace&lt;br /&gt;
#*The contents of Expressions are evaluted by EM, so they can contain mathematical formulas, functions, and complex string and date processing.&lt;br /&gt;
#&#039;&#039;&#039;Tailoring&#039;&#039;&#039;: Sometimes called &amp;quot;piping&amp;quot;, this is the process of conditionally modifying text&lt;br /&gt;
#*You have access to all &#039;replacement fields&#039;, TOKENs, and INSERTANS values&lt;br /&gt;
#*You also have easier access to questions, answers, and their properties.&lt;br /&gt;
#&#039;&#039;&#039;Relevance&#039;&#039;&#039; Equation:  A new question attribute controlling question visiblity&lt;br /&gt;
#*If there is a relevance equation, then the question is only shown if the relevance evaluates to true.&lt;br /&gt;
#*Internally, all array_filter and array_filter_exclude commands become sub-question-level relevance&lt;br /&gt;
#&#039;&#039;&#039;Equation&#039;&#039;&#039; Question Type:  A new question type that saves calculations or reports to the database&lt;br /&gt;
#*It is like a Boilerplate question, but its contents are saved to the database even if you set &amp;quot;Always Hide this Question&amp;quot;&lt;br /&gt;
#&#039;&#039;&#039;Question Code&#039;&#039;&#039;:  This is the preferred variable name for EM&lt;br /&gt;
#*This can be a descriptive name indicating the purpose of the question, making it easier to read complex logic&lt;br /&gt;
#*Valid question codes should NOT start with a number, so when using the question code to number your questions, simply use &amp;quot;q1&amp;quot;, or &amp;quot;q1a&amp;quot; or &amp;quot;g1q2&amp;quot;.&lt;br /&gt;
#*This is what currently becomes the variable name if you export data to SPSS or R, so if you do statistical analysis, you probably already made this unique.&lt;br /&gt;
&lt;br /&gt;
==Do I have to use EM?== &amp;lt;!--T:56--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:57--&amp;gt;&lt;br /&gt;
The short answer is No (but also yes).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:58--&amp;gt;&lt;br /&gt;
EM is fully backwards-compatible with existing surveys.  So, if you are happy to use Conditions and Assessments in the style that LimeSurvey used in versions &amp;lt;= 1.91+, you can continue to do so.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:59--&amp;gt;&lt;br /&gt;
However, EM completely replaces how LimeSurvey internally deals with Conditions.  Although you can still use the Conditions Editor to create and manage conditions, LimeSurvey 1.92 will convert those to the equivalent Relevance Equations.  As part of the upgrade, LimeSurvey 1.92 will auto-convert all existing Conditions to Relevance Equations.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:60--&amp;gt;&lt;br /&gt;
This should give you the best of both worlds - you can continue using LimeSurvey as you are used to, but will see the Relevance Equation equivalent so you can gradually migrate to Relevance Equations directly whenever you see fit.&lt;br /&gt;
&lt;br /&gt;
==Can I mix use of Conditions and Relevance?== &amp;lt;!--T:61--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:62--&amp;gt;&lt;br /&gt;
Yes. You can use the Conditions editor for some questions and the Relevance editor for others.  Conditions are auto-converted to Relevance when you save the question.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:63--&amp;gt;&lt;br /&gt;
Note, we assume that if you are using the Conditions editor, that you want those Conditions to over-write any manually entered Relevance equation.  So, if you have existing Conditions and want to manually edit the Relevance, please delete the Conditions for that question first.  Specifically, copy the generated relevance equation to a text editor, use the Conditions menu to delete all of the conditions for that question (which will also delete the relevance), then edit the question and paste the generated relevance equation from the text editor back into the relevance field for that question (and save the question).  If there is enough demand for deleting conditions without deleting the generated relevance equation, we could add a bulk conversion process.&lt;br /&gt;
&lt;br /&gt;
==How should I choose between Conditions and Relevance?== &amp;lt;!--T:64--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:65--&amp;gt;&lt;br /&gt;
Here is a list of pros and cons of each style:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:66--&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Style!!Pros!!Cons&lt;br /&gt;
|-&lt;br /&gt;
|Conditions||1. Nice GUI for creating simple conditions &amp;lt;br/&amp;gt;2. GUI well documented and understood by support team||1. Only supports simple comparisons and does not AND/OR conditions well &amp;lt;br/&amp;gt;2. Cascading conditions work erratically &amp;lt;br/&amp;gt;3. Slow - database intensive, so can slow down long surveys &amp;lt;br/&amp;gt;4. Some reported problems with re-loading conditions &amp;lt;br/&amp;gt;5. GUI doesn&#039;t scale well when there are dozens, hundreds, or thousands of questions &amp;lt;br/&amp;gt;6. May be slow to convert paper-based surveys since must use SGQA names &amp;lt;br/&amp;gt;7. Often need a programmer to custom-code logic needed for complex branching&lt;br /&gt;
|-&lt;br /&gt;
|Relevance||1. Supports very complex logic, including 80+ functions and math/string operators &amp;lt;br/&amp;gt;2. Perfect support for cascading logic &amp;lt;br/&amp;gt;3. Fast - no extra database calls, so supports 1000+ question surveys &amp;lt;br/&amp;gt;4. No problems with re-loading logic since does not require SGQA codes &amp;lt;br/&amp;gt;5. Syntax-highlighting scales to 1000+ question surveys &amp;lt;br/&amp;gt;6. Easy and fast to use for groups wanting to computerize existing paper-based suveys.  &amp;lt;br/&amp;gt;7. Easily supports semi-structured interviews and epidemiological surveys without needing a programmers||1. No GUI for simple conditions - use syntax-highlighting instead &amp;lt;br/&amp;gt;2. New, so support teams have not mastered EM yet.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:67--&amp;gt;&lt;br /&gt;
The bottom is that if you are happy with how LimeSurvey 1.91+ works, there is no reason to change what you do.&lt;br /&gt;
&lt;br /&gt;
==What are some other benefits of using EM?== &amp;lt;!--T:68--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:69--&amp;gt;&lt;br /&gt;
Here are some of the other reasons you might want to use EM.&lt;br /&gt;
#Calculations - you can create any calculation you can think of:&lt;br /&gt;
#*You have access to all common mathematical operators and functions&lt;br /&gt;
#*You have access to 70+ mathematical, date, and string processing functions&lt;br /&gt;
#*It is fairly easy for developers to add new functions if users need them&lt;br /&gt;
#Storing Calculations to Database&lt;br /&gt;
#*You can now compute simple and complex calculations and/or scale scores AND have them stored in the database without needing JavaScript.&lt;br /&gt;
#*You use the Equation question type to accomplish this.&lt;br /&gt;
#Assessments&lt;br /&gt;
#*You can now create assessments or scale scores from any question type, not just the subset that used to be supported&lt;br /&gt;
#*You can use Tailoring to show running or total assessment scores anywhere needed - even on the same page&lt;br /&gt;
#*You have more control over the reports generated based upon those assessment scores&lt;br /&gt;
#*You can store assessment scores in the database without needing JavaScript&lt;br /&gt;
#*You can hide assessment scores without needing JavaScript or CSS&lt;br /&gt;
#Replacement Fields&lt;br /&gt;
#*Instead of using {INSERTANS:SGQA}, you can just use the Question Code - this makes it easier to read and validate.&lt;br /&gt;
#*This also avoids the common need to edit questions to change the SGQA code to make everything work.&lt;br /&gt;
#Tailoring - you can conditionally display text based upon other values&lt;br /&gt;
#*Use the appropriate title for a subject, like (e.g. &amp;quot;Hello &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;Mr./Mrs.] Smith&amp;quot;)&lt;br /&gt;
#*Output gramatically correct sentences based when singular/plural matter:  (e.g. &amp;quot;You have 1 child&amp;quot; vs. &amp;quot;You have 2 children&amp;quot;)&lt;br /&gt;
#*Appropriately conjugate verbs and decline nouns based upon subject&#039;s gender and plurality.&lt;br /&gt;
#New Variable Attributes - you can access the following to do your tailoring:&lt;br /&gt;
#* (no suffix) -  an alias for qcode.code&lt;br /&gt;
#*.code - the selected response code for the question if it is relevant (otherwise blank), or the text value if it is not a coded question&lt;br /&gt;
#*.NAOK - same as .code, but can be part of calculations or lists even if irrelevant&lt;br /&gt;
#*.value - the assessment value for the question if it is relevant (otherwise blank), or the text value if it is not a coded question&lt;br /&gt;
#*.valueNAOK - same as .value, but can be part of calculations or lists even if irrelevant&lt;br /&gt;
#*.shown - the answer as displayed to the user (this is what {INSERTANS:xxx}  does)&lt;br /&gt;
#*.qid - the question ID&lt;br /&gt;
#*.gid - the group ID&lt;br /&gt;
#*.sgqa - the SGQA value for the question&lt;br /&gt;
#*.jsName - the correct javascript variable name for the question, regardless whether defined on this page or another&lt;br /&gt;
#*.qseq - the question sequence (starting from 0)&lt;br /&gt;
#*.gseq - the group sequence (starting from 0)&lt;br /&gt;
#*.mandatory - whether the question is mandatory (Y/N)&lt;br /&gt;
#*.question - the text of the question&lt;br /&gt;
#*.relevance - the relevance equation for the question&lt;br /&gt;
#*.grelevance - the relevance equation for the group&lt;br /&gt;
#*.relevanceStatus - whether or not the question is currently relevant (1 if true, 0 if false)&lt;br /&gt;
#*.type - the question type (the one character code)&lt;br /&gt;
#Dynamic On-Page Changes&lt;br /&gt;
#*All Relevance, Calculation, and Tailoring works dynamically on a page - so changes in values instantly update the page&lt;br /&gt;
#*So, you have questions dynamically appear/disappear based upon whether they are relevant&lt;br /&gt;
#*Questions are also dynamically tailored based upon responses on the page, so you can see running totals, tailored sentences and customized reports.&lt;br /&gt;
#New Data Entry Screen&lt;br /&gt;
#*In addition to using the current data-entry system, you can just use Survey-All-In-One.&lt;br /&gt;
#*This supports the on-page relevance and tailoring, so data entry clerks can quickly tab through and they will only have to enter the relevant responses&lt;br /&gt;
#*This can be critical if your data entry person needs to see the tailoring, which is also dynamic.&lt;br /&gt;
#Eliminates the need for most custom JavaScript&lt;br /&gt;
#*EM easily supports complicated computations, scoring, tailoring and conditional logic.&lt;br /&gt;
#*Some things will still need JavaScript (like custom layouts and conditionally hiding question sub-elements), but your JavaScript can use the EM functions so that you can access questions by their Qcode instead of SGQA, and access any of the question properties listed above.&lt;br /&gt;
&lt;br /&gt;
==What are some other helpful new features enabled by EM?== &amp;lt;!--T:70--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:71--&amp;gt;&lt;br /&gt;
Regardless of whether you continue to use the Conditions Editor or manually compose Relevance Equations, you get these additional benefits:&lt;br /&gt;
#You can create more complex validation criteria&lt;br /&gt;
#*All of the advanced question attribute (like max_answers, min_num_value_n, max_num_value) can use Expressions.  So, you min/max criteria can be easily adjusted based upon prior responses, even if they are on the same page.&lt;br /&gt;
#*EM also handles all regular-expression-based validation, so you can robustly combine preg and equation-based question attributes.&lt;br /&gt;
#Easy Re-ordering (or deleting) of Questions and Groups&lt;br /&gt;
#*Prior to version 1.92, you could not re-order questions or groups if LimeSurvey thought that such-re-ordering could break conditions in which they were used.  Similarly, you could not delete questions if any other questions depended upon them.&lt;br /&gt;
#*With EM&#039;s syntax highlighting, it is easy to see and validate whether you try to use questions before they are declared.  So, we now let you re-order or delete questions and groups whenever you like.  EM will update all of the syntax highlighting to show you potential errors.&lt;br /&gt;
#*The re-order questions view has been enhanced to help with such review.  It now shows the question&#039;s relevance equation and tailoring, so you can immediately see whether any variables become pink (meaning they are used before being declared).&lt;br /&gt;
#The Question/Group Navigation Index is always available and accurate&lt;br /&gt;
#*Prior to version 1.92, these indexes were not available if there were complex conditions&lt;br /&gt;
#*With EM, we can guarantee that they are accurate.&lt;br /&gt;
#*Subjects can even jump back, to a prior question, change the answer, then jump forward (or submit)&lt;br /&gt;
#**When jumping forwards, EM will re-validate all of the intervening questions/groups.&lt;br /&gt;
#**If any questions become irrelevant, they will be NULLed in the database so that your data is internally consistent&lt;br /&gt;
#**If any questions become relevant or newly fail mandatory or validation rules, EM will stop on that page and force the user to answer those questions before jumping to their final destination.&lt;br /&gt;
#Auto-conversion of Conditions to Relevance&lt;br /&gt;
#*When you upgrade your database, all existing surveys that have conditions will have relevance equations generated for them&lt;br /&gt;
#*Whenever you import a survey, relevance equations will be created as needed&lt;br /&gt;
#*Whenever you add, delete, or modify conditions, EM will generate the appropriate relevance equation.&lt;br /&gt;
#Convenient Syntax Highlighting&lt;br /&gt;
#*When EM shows the relevance equation, it will show the Qcode, even if you entered an SGQA code, as we assume this will be easier to read.&lt;br /&gt;
#*All variables are color coded to show whether they were declared before or after the current question (or before or after the current group).  This lets you quickly detect and fix cases where you try to use variables for relevance (including array_filter), tailoring, or validation equations prior to declaring them.&lt;br /&gt;
#*In addition, if you hover your mouse over the color-coded variable, you will see the most important metadata about that question.   This includes the Group Sequence #, Question Sequence #, Qcode, Text of the question, and all available answer choices (if it is a question type with enumerated answer choices).&lt;br /&gt;
#**The list of answer choices uses this syntax:  &#039;answers&#039;:{key:val, ... }.&lt;br /&gt;
#**&#039;&#039;key&#039;&#039; has the syntax &#039;&#039;&#039;&#039;scale~code&#039;&#039;&#039;&#039; where &#039;&#039;scale&#039;&#039; is the answer scale (e.g. for dual scale), and &#039;&#039;code&#039;&#039; is the answer code.&lt;br /&gt;
#**&#039;&#039;val&#039;&#039; has the syntax &#039;&#039;&#039;&#039;value~shown&#039;&#039;&#039;&#039; where &#039;&#039;value&#039;&#039; is the assessment value (if using assessments, otherwise &#039;&#039;code&#039;&#039;)(e.g. Qcode.value), and &#039;&#039;shown&#039;&#039; is the display value as seen by the subject (e.g. Qcode.shown)&lt;br /&gt;
#**This means that many surveys can use calculations without needing assessment mode.  If you have enumerated answer options  that are unique, non-decimal, and non-negative, you can simply do calculations on the Qcode.code values.&lt;br /&gt;
#Easy review of entire survey logic and content&lt;br /&gt;
#*There is a new Show Survey Logic feature that lets you see everything about the survey (or group or question) on a single page.&lt;br /&gt;
#*It shows the Group, Question, Sub-Question, and Answer-level details for the selected scope (survey vs. group vs. question)&lt;br /&gt;
#*It also shows the relevance, sub-question-level relevance (for array_filter and array_filter_exclude), and generated validation equation (for preg and any validation rules like min/max sum/number of values), and all non-blank question attributes.&lt;br /&gt;
#*Everything is syntax-highlighted so that you can see potential syntax errors (like unbalanced parentheses or use of variables before they were declared)&lt;br /&gt;
#*The syntax-highligting supports rapid navigation and editing of the survey.&lt;br /&gt;
#**If you click on a variable name, it opens a browser window (or tab) that shows you that question and lets you edit it.&lt;br /&gt;
#**If you click on a group name, it opens a browser window (or tab) showing the group-reorder view so that you can easily move questions around.&lt;br /&gt;
#**All of the question attributes are also syntax highlighted.  This lets you set and see expressions within advanced question options (like basing the max/min number/sum of values on an expression)&lt;br /&gt;
#*The EM author used similar view (a little cleaner) to let his collaborating Epidemiologists and Institutional Review Board validate and authorize surveys with thousands of questions in highly branched and tailored structured interviews&lt;br /&gt;
&lt;br /&gt;
==How Backwards Compatible is EM with 1.91+?== &amp;lt;!--T:72--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:73--&amp;gt;&lt;br /&gt;
LimeSurvey 1.92 is fully backwards-compatible with 1.91+ with one exception/caveat:  1.92 handles less-than / greater-than comparisons against empty values differently than 1.91+.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:74--&amp;gt;&lt;br /&gt;
One of the LimeSurvey demo surveys uses a set of conditions that translates to this relevance equation:  {(age &amp;lt; 16) or (age == 20) or ... or (age == 80)}. In LimeSurvey 1.91+, (age &amp;lt; 16) is FALSE when there is no answer (the value is blank).  However, in LimeSurey 1.92, (age &amp;lt; 16) is TRUE when there is no answer, since both PHP and JavaScript treat blank as 0 in mathematical comparisons.  Thus, 1.91+ would hide that question when age was unanswered, but 1.92 would show it.  We went to great pains to prevent this, but since we needed to have the Expressions generate identical results in PHP and JavaScript, there was no way to make 1.92 treat &amp;quot;&amp;quot; &amp;lt; 16 as FALSE.  Fortunately, there is an easy work-around for this.  If you want (age &amp;lt; 16) to be FALSE, then use this expression instead: {(!is_empty(age) and age &amp;lt; 16)}.  You can use the new [[Show Logic File|Survey Logic File]] view to quickly identify and fix any such comparisons in your survey.&lt;br /&gt;
&lt;br /&gt;
=Getting Started= &amp;lt;!--T:75--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:76--&amp;gt;&lt;br /&gt;
The best way to get started with EM is to:&lt;br /&gt;
*Install the latest stable version from http://www.limesurvey.org/en/download &lt;br /&gt;
*Import and explore the [[Expression Manager Sample Surveys|sample surveys]].&lt;br /&gt;
*Explore the [[Expression Manager HowTos|use cases and HowTos]] and [[Expression Manager Examples|step-by-step examples]].&lt;br /&gt;
*Explore the EM documentation (this page)&lt;br /&gt;
*Examine the built-in EM test suite&lt;br /&gt;
**From any survey, under tools, select the EM option&lt;br /&gt;
**Available Functions lists the 70+ functions and syntax&lt;br /&gt;
**Unit Tests of Isolated Expressions&lt;br /&gt;
***shows examples of using all EM functions and operators, and the PHP and JavaScript results&lt;br /&gt;
***note there are few functions that generate different results in the PHP and JavaScript versions, so this page lets you plan your EM logic accordingly.&lt;br /&gt;
&lt;br /&gt;
=What Functionality does Expression Manager Extend/Replace? (LimeSurvey &amp;lt;= 1.91+)= &amp;lt;!--T:77--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Conditions =&amp;gt; Relevance== &amp;lt;!--T:78--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:79--&amp;gt;&lt;br /&gt;
Conditions controlled which  questions are visible.  The general syntax was &#039;&#039;SGQA operator Value&#039;&#039;, like &#039;&#039;111X2X3 == &amp;quot;Y&amp;quot;&#039;&#039;.  Conditions could be ANDed or ORed together, but mixing ANDs and ORs was difficult.  The conditions themselves were stored in a separate table, and large portion of LimeSurvey&#039;s code was devoted to managing Conditions.  Because of extensive database access, processing large numbers of conditions could cause noticable performance problems.  Furthermore, once you had conditions assigned to questions or groups, you were often not allowed to re-order or delete them.&lt;br /&gt;
&lt;br /&gt;
==Assessments =&amp;gt; Equations and  Micro-Tailoring== &amp;lt;!--T:80--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:81--&amp;gt;&lt;br /&gt;
Assessments let users create scale scores from a collection of questions.  However, they could not dynamically change on the current page, and their values were not stored to the database.&lt;br /&gt;
&lt;br /&gt;
==Replacements =&amp;gt; Micro-Tailoring== &amp;lt;!--T:82--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:83--&amp;gt;&lt;br /&gt;
Users could tailor some messages and questions based  upon prior responses.  For example, a question might be, &#039;&#039;{TOKEN:FIRSTNAME}, you said {INSERTANS:111X3X4} was your favorite sport&#039;&#039;.  However, it was not possible to do conditional tailoring (like say &amp;quot;Mr.&amp;quot; or &amp;quot;Mrs.&amp;quot; depending upon the person&#039;s gender), or conjugate verbs or decline nouns without fancy JavaScript.  Authors could implement surveys that seemed to tailor questions, but it required separate questions for each permutation, and complex conditions to decide which questions to display.&lt;br /&gt;
&lt;br /&gt;
==Validation== &amp;lt;!--T:84--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:85--&amp;gt;&lt;br /&gt;
Question could be validated with Regular expressions, or minimum/maximum values, or let an SGQA response serve as the minimum or maximum value.  However, validations could not be based upon calculations of other variables without fancy JavaScript.&lt;br /&gt;
&lt;br /&gt;
==Equations== &amp;lt;!--T:86--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:87--&amp;gt;&lt;br /&gt;
Equations were not supported without fancy JavaScript.&lt;br /&gt;
&lt;br /&gt;
==Equation Question Type== &amp;lt;!--T:88--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:89--&amp;gt;&lt;br /&gt;
Equations could not be saved to the database (e.g. the final score for an assessment) without fancy JavaScript.&lt;br /&gt;
&lt;br /&gt;
=How Will Expression Manager Replace/Extend That Functionality?= &amp;lt;!--T:90--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:91--&amp;gt;&lt;br /&gt;
The Expression Manager is a new core module within LimeSurvey that makes it much easier to support the type of complex functionality that used to require custom JavaScript.  It is also replacing the way LimeSurvey currently manages Conditions and Assessments.&lt;br /&gt;
&lt;br /&gt;
==New Terminology When Referring to Expression Manager (EM)== &amp;lt;!--T:92--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:93--&amp;gt;&lt;br /&gt;
EM &amp;quot;thinks&amp;quot; of its functionality in the following terms:&lt;br /&gt;
*&#039;&#039;&#039;Relevance-based Branching&#039;&#039;&#039; - if a question is relevant, then ask it, otherwise don&#039;t (e.g. make it invisible, and mark it as NULL in the database).  There is a new Relevance field for all Question types, and also for each Group (so you can apply a set of conditions to an entire group without having to copy the same condition to each question, and/or combine group and question-level conditional logic).&lt;br /&gt;
*&#039;&#039;&#039;Tailoring&#039;&#039;&#039; - Once you know which questions should be asked, tailoring (sometimes called &#039;&#039;piping&#039;&#039;) specifies how the question should be asked. This lets you support not only simple subsitution (like {TOKEN:FIRSTNAME}), but also conjugation of verbs and declination of nouns based upon the gender or number of your subjects.  It also lets you change the message you deliver to a subject based upon whether they answered (or how they answered) other questions.&lt;br /&gt;
*&#039;&#039;&#039;Equations&#039;&#039;&#039; - EM adds a new question type called Equation which stores the result of an Expression.  These equations results are computed and written to the database, even if you hide them on the page.  Thus, they are useful for hidden scoring calculations, navigation based upon complex equations, assessments, and reports that should be generated and easily available within the database.&lt;br /&gt;
&lt;br /&gt;
===Relevance and Cascading Relevance=== &amp;lt;!--T:94--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:95--&amp;gt;&lt;br /&gt;
Every question type now has a Relevance option which controls whether the question is displayed.  EM processes each of the Relevance Equations in the order they should appear in the survey.  If the expression is true (or missing - to support legacy surveys), the question will be displayed. If it is not relevant, then the question will be hidden, and the value will be NULLed in the database.  If there are no relevant questions in a group, the entire group will be skipped.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:96--&amp;gt;&lt;br /&gt;
Moreover, if any of the variables within an expression is irrelevant, then the expression always evaluates to false.  This enables Cascading Relevance so that you do not have to write very long Relevance equations for each question.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:97--&amp;gt;&lt;br /&gt;
Say you have 5 questions Q1-Q5, and you only want to show Q2 if Q1 was answered, and Q3 if Q2 was answered, etc.  The relevance equations might be:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:98--&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Question Code!!Relevance!!Question&lt;br /&gt;
|-&lt;br /&gt;
|Q1||1||What is your name?&lt;br /&gt;
|-&lt;br /&gt;
|Q2||Q1||{Q1}, how old are you?&lt;br /&gt;
|-&lt;br /&gt;
|Q3||Q2||So, you are {Q2} years old.  Are you married?&lt;br /&gt;
|-&lt;br /&gt;
|Q4||Q3 == &amp;quot;Y&amp;quot;||{Q1}, how long have you been married?&lt;br /&gt;
|-&lt;br /&gt;
|Q5||Q4||How many children do you have, {Q1}?&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:99--&amp;gt;&lt;br /&gt;
The relevance calculations also work in JavaScript - so you could put all the above questions on one page and it would still work as expected.  In fact, EM totally replaces how EM processes Survey vs. Group vs. Question-at-a-time survey formats.  They now all use the exactly same navigation engine so they work identically regardless of survey style.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:100--&amp;gt;&lt;br /&gt;
As long as you are on the same page, any data you entered will still be there, just hidden.  So, if you enter some information, then choose an option that makes them irrelevant, then make them relevant again, your answers will still be available.  However, as soon as you move to a different page, all irrelevant responses will be lost to integrity of the dataset.&lt;br /&gt;
&lt;br /&gt;
===Group-Level Relevance=== &amp;lt;!--T:101--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:102--&amp;gt;&lt;br /&gt;
Expression Manager also supports group-level relevance.  This makes it easier to implement looping.   Say you want to collect information about up to 10 entities (such a products or people in a household), where you first determine how many entities need follow-up (such as by asking how many people live in a household, or having people check which products they like from a long list).  After knowning how many entities need follow-up, you can use Group-level relevance like {count &amp;gt;= 1}, {count &amp;gt;=2}, ... {count &amp;gt;= 10} for each of the 10 groups of follow-up questions.  Within each group, you can have question-level conditional logic (e.g. gender or age-specific follow-up questions for each subject).  The question and group-level relevance equations are ANDed together to determine which should be shown.&lt;br /&gt;
&lt;br /&gt;
===Tailoring / Piping=== &amp;lt;!--T:103--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:104--&amp;gt;&lt;br /&gt;
Anything within curly braces is now treated as an Expression (with one exception described below).  Expressions have acccess to all of the LimeReplacementFields, all of the variables (via several aliases), all typical equation operators (mathematical, logical, and comparison), and dozens of functions (that even work dynamically on the client-side).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:105--&amp;gt;&lt;br /&gt;
Using these equations, you can do things such as:&lt;br /&gt;
#Conditionally show tailored messages to the respondants based upon prior responses&lt;br /&gt;
#Create Assessments and show Assessment results (or conditionally branch or show messages) based upon those results, all without using the Assessments module itself&lt;br /&gt;
#Conjugate verbs and decline nouns within questions, answers, and reports.&lt;br /&gt;
#Show summaries of responses before the &amp;quot;Show your answers&amp;quot; page at the end of the survey&lt;br /&gt;
&lt;br /&gt;
===Equations=== &amp;lt;!--T:106--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:107--&amp;gt;&lt;br /&gt;
There is a new question type called  Equation.  It is like a Boilerplate questions, except that it stores the value of what is displayed in the database.  So, if the Equation Question text contains an Assessment computation, that value would be stored in the database in a variable that can be displayed within public or private statistics.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:108--&amp;gt;&lt;br /&gt;
This solves a common request for storing Assessment scores within the database&lt;br /&gt;
&lt;br /&gt;
==Syntax== &amp;lt;!--T:109--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:110--&amp;gt;&lt;br /&gt;
Anything contained within curly braces is now considered an Expression (with one exception:  there must be no leading or trailing whitespace - this is needed to ensure the Expression Manager does not try to process embedded JavaScript).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:111--&amp;gt;&lt;br /&gt;
Note, it is OK for expressions to span multiple lines, as long as there is no whitespace after the opening  curly brace or before the closing curly brace.  This is especially helpful for nested if() statements like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:112--&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;{if(is_empty(PFTotals),&lt;br /&gt;
 &#039;&#039;,&lt;br /&gt;
 if(PFTotals &amp;gt;= -5 &amp;amp;&amp;amp; PFTotals &amp;lt;= -4,&lt;br /&gt;
   &#039;Very Soft&#039;,&lt;br /&gt;
   if(PFTotals &amp;gt;= -3 &amp;amp;&amp;amp; PFTotals &amp;lt;= -2,&lt;br /&gt;
     &#039;Soft&#039;,&lt;br /&gt;
     if(PFTotals == -1,&lt;br /&gt;
       &#039;Somewhat Soft&#039;,&lt;br /&gt;
       if(PFTotals == 0,&lt;br /&gt;
         &#039;Moderate&#039;,&lt;br /&gt;
         if(PFTotals == 1,&lt;br /&gt;
           &#039;Somewhat Hard&#039;,&lt;br /&gt;
           if(PFTotals &amp;gt;= 2 &amp;amp;&amp;amp; PFTotals &amp;lt;= 3,&lt;br /&gt;
             &#039;Hard&#039;,&lt;br /&gt;
             if(PFTotals &amp;gt;= 4 &amp;amp;&amp;amp; PFTotals &amp;lt;= 5,&lt;br /&gt;
               &#039;Very Hard&#039;,&lt;br /&gt;
               &#039;&#039;&lt;br /&gt;
             )&lt;br /&gt;
           )&lt;br /&gt;
         )&lt;br /&gt;
       )&lt;br /&gt;
     )&lt;br /&gt;
   )&lt;br /&gt;
 )&lt;br /&gt;
)}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:138--&amp;gt;&lt;br /&gt;
&amp;lt;div id=&amp;quot;EMsyntax&amp;quot;&amp;gt;Expression Manager supports the following syntax:&amp;lt;/div&amp;gt;&lt;br /&gt;
*All standard mathematical operators (e.g. +,-,*,/,!)&lt;br /&gt;
*All standard comparison operators (e.g. &amp;lt;,&amp;lt;=,==,!=,&amp;gt;,&amp;gt;=, plus these equivalents:  lt,le,eq,ne,gt,ge)&lt;br /&gt;
*Parentheses (so you can group sub-expressions)&lt;br /&gt;
*Conditional operators (e.g. &amp;amp;&amp;amp;,| | and these equivalents: and,or)&lt;br /&gt;
*Single and double-quoted strings (which can each embed strings with the other quote type)&lt;br /&gt;
*Comma operator (so can have a list of expressions and just return the final result)&lt;br /&gt;
*Assignment operator (=)&lt;br /&gt;
*Pre-defined variables (to refer to questions, question attributes, and responses) - e.g. all of the SGQA codes&lt;br /&gt;
*Pre-defined functions (there are already 70+, and it is easy to add more)&lt;br /&gt;
&lt;br /&gt;
=== Operators === &amp;lt;!--T:211--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:139--&amp;gt;&lt;br /&gt;
EM syntax follows normal operator precedence:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:140--&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Level!!Operator(s)!!Description&lt;br /&gt;
|-&lt;br /&gt;
|1||()||parentheses for grouping or calling functions&lt;br /&gt;
|-&lt;br /&gt;
|2||! - +||unary operators: not, negation, unary-plus&lt;br /&gt;
|-&lt;br /&gt;
|3||* /||times, divide&lt;br /&gt;
|-&lt;br /&gt;
|4||+ -||plus, minus&lt;br /&gt;
|-&lt;br /&gt;
|5||&amp;lt; &amp;lt;= &amp;gt; &amp;gt;= lt le gt ge||relative comparisons&lt;br /&gt;
|-&lt;br /&gt;
|6||== != eq ne||equality comparisons&lt;br /&gt;
|-&lt;br /&gt;
|7||and||logical AND&lt;br /&gt;
|-&lt;br /&gt;
|8||or||logical OR&lt;br /&gt;
|-&lt;br /&gt;
|9||=||assignment operator&lt;br /&gt;
|-&lt;br /&gt;
|10||,||comma operator&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:141--&amp;gt;&lt;br /&gt;
Note, for consistency between JavaScript and PHP, the plus operator (+) does addition if both operands are numeric, but does concatenation if both parts are non-numeric strings.  However, we recommend using the join() function for concatenation, as that makes your intent more clear, and avoids unexpected results if you were expecting strings but got numbers instead (or vice versa).&lt;br /&gt;
&lt;br /&gt;
===Caution about using Assignment Operator (=)=== &amp;lt;!--T:142--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:143--&amp;gt;&lt;br /&gt;
Note, you should avoid using the assignment operators unless absolutely necessary, since they may cause unexpected side-effects.  For example, if you change the value of a previous response, the cascading relevance and validation logic between that question and the current question is not re-computed, so you could end up with internally inconsistent data (e.g. questions that stay answered but should have been NULLed, or questions that are skipped but should have been answered).  In general, if you want to assign a value to a variable, you should create an Equation question type, and use an expression to set its value.  However, there are some rare times that people really need this operator, so we made it available.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:144--&amp;gt;&lt;br /&gt;
To help caution you about this operator, it is shown in red font within the syntax equations (so that you don&#039;t confuse it with &amp;quot;==&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
===Using Assignment Operator=== &amp;lt;!--T:145--&amp;gt;&lt;br /&gt;
The main reasons you may want to use assignment are:&lt;br /&gt;
*You need to set the default value for a question that does not accept defaults via equation (such as list radio, where the user interface lets you pick one of the answer options, but does not let you enter an equation).  However, be careful, as LimeSurvey will not be able to validate that your equation generates one of the allowable answers for that question.&lt;br /&gt;
*You need to forcibly change the response to a previous question based upon a later response&lt;br /&gt;
* etc...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:212--&amp;gt;&lt;br /&gt;
You can use all expression manager system for this purpose. It&#039;s better to use an [[Question_type_-_Equation|Equation question]] type to this purpose.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:213--&amp;gt;&lt;br /&gt;
Some example:&lt;br /&gt;
* Set answer to a short text question in lowercase : &amp;lt;code&amp;gt;{QCODE=strtolower(QCODE.NAOK)}&amp;lt;/code&amp;gt;&lt;br /&gt;
* Set a default answer to an array question type at start of a survey : &amp;lt;code&amp;gt;{Q1_SQ1=(is_empty(Q1_SQ1.NAOK),&amp;quot;A99&amp;quot;,Q1_SQ1.NAOK)}&amp;lt;/code&amp;gt;&lt;br /&gt;
* Set a default answer to an array texts question type at start of a survey : &amp;lt;code&amp;gt;{Q1_SQY1_SQX1 = (is_empty(Q1_SQY1_SQX1.NAOK),&amp;quot;Inserted answer&amp;quot;, Q1_SQY1_SQX1.NAOK)}&amp;lt;/code&amp;gt;&lt;br /&gt;
* Set an answer with condition : &amp;lt;code&amp;gt;{QCODE=if(YesNo=&amp;quot;Y&amp;quot;,&amp;quot;A1&amp;quot;,&amp;quot;&amp;quot;)}&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== XSS security == &amp;lt;!--T:214--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:215--&amp;gt;&lt;br /&gt;
With XSS enable, some expression manager system can not be used : &lt;br /&gt;
* starting a HTML tag in expression but ending in another expression&lt;br /&gt;
* use a complex expression in URL. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:216--&amp;gt;&lt;br /&gt;
Example and workaround&lt;br /&gt;
* &amp;lt;code&amp;gt;{if( 1 ,&amp;quot;&amp;amp;lt;strong&amp;amp;gt;&amp;quot;,&amp;quot;&amp;quot;)}information{if( 1 ,&amp;quot;&amp;amp;lt;/strong&amp;amp;gt;&amp;quot;,&amp;quot;&amp;quot;)}&amp;lt;/code&amp;gt; is broken with XSS security, here you can use &amp;lt;code&amp;gt;{if(1,&amp;quot;&amp;lt;strong&amp;amp;gt;information&amp;amp;lt;/strong&amp;amp;gt;&amp;quot;,&amp;quot;information&amp;quot;)}&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;&amp;amp;lt;a href=&amp;quot;/script.php?value={if(QCODE == &amp;quot;Y&amp;quot;,&amp;quot;yes&amp;quot;,&amp;quot;no&amp;quot;)}&amp;quot;&amp;amp;gt;next&amp;amp;lt;/a&amp;amp;gt;&amp;lt;/code&amp;gt;, here you can use an equation question because using a complete question code is OK : &amp;lt;code&amp;gt;&amp;amp;lt;a href=&amp;quot;/script.php?value={EQUATION.NAOK}&amp;quot;&amp;amp;gt;next&amp;amp;lt;/a&amp;amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Access to Variables== &amp;lt;!--T:146--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:147--&amp;gt;&lt;br /&gt;
Expression Manager provides read-only access to whichever variables we might need.  For backwards compatibility, it provides access to the following:&lt;br /&gt;
*TOKEN:xxx - the value of a TOKEN (e.g. TOKEN:FIRSTNAME, TOKEN:ATTRIBUTE_5) (Only for NOT anonymous survey).&lt;br /&gt;
*[[Adding a question#Information_from_previous_answers|INSERTANS:SGQA]] - the display value of an answer (e.g. &amp;quot;Yes&amp;quot;). For Expression Manager it&#039;s the same that using {QCODE.shown}.&lt;br /&gt;
*All [[The_template_editor#Keywords|{XXX} values used by templates]].&lt;br /&gt;
*In question text, you can use {QID} replaced by the question id and {SGQ} replaced by the SGQA of the question&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:148--&amp;gt;&lt;br /&gt;
In addition, Expression Manager lets you refer to variables by the Question Code (the &#039;title&#039; column in the questions table within the database).  This is also the variable label used when you export your data to SPSS, R, or SAS.  For example, if you have questions about name, age, and gender, you could call those variables &#039;&#039;name&#039;&#039;, &#039;&#039;age&#039;&#039;, and &#039;&#039;gender&#039;&#039; instead of &#039;&#039;12345X13X22&#039;&#039;, &#039;&#039;12345X13X23&#039;&#039;, and  &#039;&#039;12345X13X24&#039;&#039;.  This makes equations easier for everyone to read and validate the logic, plus makes it possible to shuffle questions around without having to keep track of group or question numbers.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:210--&amp;gt;&lt;br /&gt;
&amp;lt;div class=&#039;simplebox&#039;&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Important:&#039;&#039;&#039; It is only safe to refer to variables that occur in preceding pages or questions.&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:149--&amp;gt;&lt;br /&gt;
Furthermore, Expression Manager lets you access many properties of the Question:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:150--&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Syntax!!Meaning!!Example!!Example Result&lt;br /&gt;
|-&lt;br /&gt;
|Qcode||an alias for Qcode.code||{implode(&#039;,&#039;,name,gender)}||&#039;Tom&#039;,&#039;M&#039;&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.code||the selected response code for the question if it is relevant (otherwise blank), or the text value if it is not a coded question||{implode(&#039;,&#039;,name.code,gender.code)}||&#039;Tom&#039;,&#039;M&#039;&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.NAOK||same as Qcode - see discussion of NAOK||{gender.NAOK}||&#039;M&#039;&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.value||the assessment value for the question if it is relevant (otherwise blank), or the text value if it is not a coded question||{gender.value}||&#039;1&#039;&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.valueNAOK||same as Qcode.value - see discussion about NAOK||{gender.valueNAOK}||&#039;1&#039;&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.shown||the dispay value for the question||{implode(&#039;,&#039;,name.shown,gender.shown)}||&#039;Tom&#039;,&#039;Male&#039;&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.question||the text of the question||{gender.question}||&#039;What is your gender?&#039;&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.mandatory||whether the question is mandatory (Y/N)||{gender.mandatory}||&#039;N&#039;&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.qid||the internal question number (not the sequential number)||{gender.qid}||337&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.type||the question type||{gender.type}||&#039;G&#039;&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.jsName||the correct javascript name for the question, regardless whether declared on or off this page||{gender.jsName}||&#039;java1827X3X337&#039;&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.gid||the internal group number (not the sequential number)||{gender.gid}||3&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.qseq||the sequential number of the question, starting from 0||{gender.qseq}||5&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.gseq||the sequential number of the group, starting from 0||{gender.gseq}||1&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.relevanceStatus||whether the question is currently relevant (0 or 1)||{gender.relevanceStatus}||1&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.relevance||the question-level relevance equation||{gender.relevance}||&#039;!is_empty(name)&#039;&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.grelevance||the  group-level relevance equation||{gender.grelevance}||&#039;num_children &amp;gt;= 5&#039;&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.sgqa||the SGQA value for this question||{gender.sgqa}||&#039;1827X3X337&#039;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== HTML editor issue=== &amp;lt;!--T:151--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:217--&amp;gt;&lt;br /&gt;
{{Alert|This issue is fixed after 2.05 build 140803}} &lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:152--&amp;gt;&lt;br /&gt;
If you use HTML editor, some characters are replaced by HTML entities.&lt;br /&gt;
* &amp;amp; by &amp;amp;amp;amp;&lt;br /&gt;
* &amp;lt; by &amp;amp;amp;lt;&lt;br /&gt;
* &amp;gt; by &amp;amp;amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:209--&amp;gt;&lt;br /&gt;
If you use HTML editor you need to use :&lt;br /&gt;
* and for &amp;amp;&lt;br /&gt;
* lt for &amp;lt;&lt;br /&gt;
* le for &amp;lt;=&lt;br /&gt;
* gt for &amp;gt;&lt;br /&gt;
* ge for &amp;gt;=&lt;br /&gt;
&lt;br /&gt;
==Qcode Variable Naming== &amp;lt;!--T:153--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:154--&amp;gt;&lt;br /&gt;
Here are the details of how to construct a Qcode (and access some properties) by question type.  In general, Qcodes are constructed as:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:155--&amp;gt;&lt;br /&gt;
  QuestionCode . &#039;_&#039; . SubQuestionID . &#039;_&#039; . ScaleId&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:208--&amp;gt;&lt;br /&gt;
For comment and other, question code are QuestionCode_comment and QuestionCode_other&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:156--&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Type!!Description!!Code!!SubQs!!Answer Options!!Scales!!Answer Code!!Answer Shown!!Relevance&lt;br /&gt;
|-&lt;br /&gt;
|5||5 Point Choice Radio-Buttons||Q1|| ||1-5|| ||{Q1}||{Q1.shown}||{Q1==3}&lt;br /&gt;
|-&lt;br /&gt;
|B||Array (10 Point Choice) Radio-Buttons||Q2||L1-L6||1-10|| ||{Q2_L2}||{Q2_L2.shown}||{Q2_L2==7}&lt;br /&gt;
|-&lt;br /&gt;
|A||Array (5 Point Choice) Radio-Buttons||Q3||1-5||1-5|| ||{Q3_1}||{Q3_1.shown}||{Q3_1&amp;gt;=3}&lt;br /&gt;
|-&lt;br /&gt;
|1||Array (Flexible Labels) Dual Scale||Q4||sq1-sq5||0:a1-a3||1:b1-b3||{Q4_sq1_0}||{Q4_sq1_1.shown}||{Q4_sq1_1==&#039;b2&#039;}&lt;br /&gt;
|-&lt;br /&gt;
|H||Array (Flexible) - Column Format||Q5||1-5||s,m,t|| ||{Q5_1}||{Q5_1.shown}||{Q5_1==&#039;s&#039;}&lt;br /&gt;
|-&lt;br /&gt;
|F||Array (Flexible) - Row Format||Q6||F1-F5||1-5|| ||{Q6_F3}||{Q6_F3.shown}||{Q6_F3==4}&lt;br /&gt;
|-&lt;br /&gt;
|E||Array (Increase/Same/Decrease) Radio-Buttons||Q7||1-7||I,S,D|| ||{Q7_4}||{Q7_4.shown}||{Q7_4==&#039;D&#039;}&lt;br /&gt;
|-&lt;br /&gt;
|:||Array (Multi Flexi) 1 To 10||Q8||ls1,todo,ls2||min,max,avg|| ||{Q8_ls1_max}||{Q8_ls2_avg.shown}||{Q8_ls2_min==7}&lt;br /&gt;
|-&lt;br /&gt;
|;||Array (Multi Flexi) Text||Q9||hp,st,sw||1st,2nd,3rd|| ||{Q9_hp_3rd}||{Q9_hp_3rd.shown}||{Q9_hp_3rd==&#039;Peter&#039;}&lt;br /&gt;
|-&lt;br /&gt;
|C||Array (Yes/Uncertain/No) Radio-Buttons||Q10||1-5||Y,N,U|| ||{Q10_1}||{Q10_1.shown}||{Q10_3==&#039;Y&#039;}&lt;br /&gt;
|-&lt;br /&gt;
|X||Boilerplate Question||Q11|| || || || ||{Q11.shown}||&lt;br /&gt;
|-&lt;br /&gt;
|D||Date||Q12|| || || ||{Q12}||{Q12.shown}||&lt;br /&gt;
|-&lt;br /&gt;
|*||Equation||Q13|| || || ||{Q13}||{Q13.shown}||{Q13&amp;gt;5}&lt;br /&gt;
|-&lt;br /&gt;
|~124~||File Upload (records number of files uploaded)||Q14|| || || ||{Q14}|| ||{Q14&amp;gt;0}&lt;br /&gt;
|-&lt;br /&gt;
|G||Gender Drop-Down List||Q15|| ||M,F|| ||{Q15}||{Q15.shown}||{Q15==&#039;M&#039;}&lt;br /&gt;
|-&lt;br /&gt;
|U||Huge Free Text||Q16|| || || ||{Q16}||{Q16.shown}||{strlen(Q16)&amp;gt;100}&lt;br /&gt;
|-&lt;br /&gt;
|I||Language Question||Q17|| || || ||{Q17}||{Q17.shown}||{Q17==&#039;en&#039;}&lt;br /&gt;
|-&lt;br /&gt;
|!||List - Dropdown||Q18|| ||1-5|| ||{Q18}||{Q18.shown}||{Q18==3}&lt;br /&gt;
|-&lt;br /&gt;
|L||List Drop-Down/Radio-Button List||Q19|| ||A-Z|| ||{Q19}||{Q19.shown}||{Q19==&#039;X&#039;}&lt;br /&gt;
|-&lt;br /&gt;
|O||List With Comment Drop-Down/Radio-Button List + Textarea||Q20|| ||A-F|| ||{Q20},{Q20comment}||{Q20.shown}||{Q20==&#039;B&#039;}&lt;br /&gt;
|-&lt;br /&gt;
|T||Long Free Text||Q21|| || || ||{Q21}||{Q21.shown}||{strstr(Q21,&#039;hello&#039;)&amp;gt;0}&lt;br /&gt;
|-&lt;br /&gt;
|M||Multiple Choice Checkbox||Q22||A-F, other|| || ||{Q22_E}, {Q22_other}||{Q22_E.shown}, {Q22_other}||{Q22_E==&#039;Y&#039;}&lt;br /&gt;
|-&lt;br /&gt;
|P||Multiple Choice With Comments Checkbox + Text||Q23||A-F|| || ||{Q23_D}, {Q23_Dcomment}||{Q23_D.shown}||{!is_empty(Q23)}&lt;br /&gt;
|-&lt;br /&gt;
|K||Multiple Numerical Question||Q24||self,mom,dad|| || ||{Q24_self}||{Q24_self.shown}||{Q24_self&amp;gt;30}&lt;br /&gt;
|-&lt;br /&gt;
|Q||Multiple Short Text||Q25||A-F|| || ||{Q25_B}||{Q25_B.shown}||{substr(Q25_B,1,1)==&#039;Q&#039;}&lt;br /&gt;
|-&lt;br /&gt;
|N||Numerical Question Type||Q26|| || || ||{Q26}||{Q26.shown}||{Q26 &amp;gt; 30}&lt;br /&gt;
|-&lt;br /&gt;
|R||Ranking Style||Q27||1-4|| || ||{Q27_1}||{Q27_1.shown}||{Q27_1==3}&lt;br /&gt;
|-&lt;br /&gt;
|S||Short Free Text||Q28|| || || ||{Q28}||{Q28.shown}||{Q28==&#039;mine&#039;}&lt;br /&gt;
|-&lt;br /&gt;
|Y||Yes/No Radio-Buttons||Q29|| || || ||{Q29}||{Q29.shown}||{Q29==&#039;Y&#039;}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==The reserved &#039;this&#039;, &#039;self&#039;, and &#039;that&#039; variables== &amp;lt;!--T:157--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:158--&amp;gt;&lt;br /&gt;
Quite often, you want to evalute all parts of a question, such as counting how many sub-questions have been answered, or summing the scores.  Other times, you want to process just certain rows or columns of a question (such as getting the row or column sums and storing them in the database).  These reserved variables make that process relatively painless.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:159--&amp;gt;&lt;br /&gt;
The &#039;this&#039; variable is used exclusively within the &amp;quot;Whole question validation equation&amp;quot; and &amp;quot;Sub-question validation equation&amp;quot; advanced question options.  It expands to the variable names of each of the cells within those questions.  So, if you want to make sure that each entry is greater than three, you would set the &amp;quot;Sub-question validation equation&amp;quot; to (this &amp;gt; 3).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:160--&amp;gt;&lt;br /&gt;
The &#039;self&#039; and &#039;that&#039; variable are more powerful, and serve as macros which are expanded prior to processing equations.  The syntax choices are:&lt;br /&gt;
*self&lt;br /&gt;
*self.&#039;&#039;suffix&#039;&#039;&lt;br /&gt;
*self.&#039;&#039;sub-selector&#039;&#039;&lt;br /&gt;
*self.&#039;&#039;sub-selector&#039;&#039;.&#039;&#039;suffix&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:161--&amp;gt;&lt;br /&gt;
&#039;&#039;suffix&#039;&#039; is any of the normal qcode suffixes (e.g. NAOK, value, shown)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:162--&amp;gt;&lt;br /&gt;
&#039;&#039;sub-selector&#039;&#039; is one of:&lt;br /&gt;
*comments - only subquestions that are comments (e.g. from multiple choice with comment and list with comment)&lt;br /&gt;
*nocomments - only subquestions that are not comments&lt;br /&gt;
*sq_X - where X is a row or column identifier.  Only sub-questions matching pattern X are selected. Note that search is done on complete code identifier, then sq_X match and include subquestions nX, X, Xn (e.g. if you use sq_1, subquestions a1, 1a, 1, 11 or 001 was included). Put attention at dual scale question type where subquestions code are QCODE_SQCODE_1 and QCODE_SQCODE_1 and to ranking question type where subquestions code are QCODE_1,QCODE_2 ....&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:163--&amp;gt;&lt;br /&gt;
Examples:&lt;br /&gt;
*Has any part of a question been answered?  {count(self.NAOK)&amp;gt;0}&lt;br /&gt;
*What is the assessment score for this question?  {sum(self.value)}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:164--&amp;gt;&lt;br /&gt;
You can also use these to get row and column totals.  Say you have a array of numbers with rows A-E and columns 1-5.&lt;br /&gt;
*What is the grand total?  {sum(self.NAOK)}&lt;br /&gt;
*What is the total of row B?  {sum(self.sq_B.NAOK)}&lt;br /&gt;
*What is the total of column 3? {sum(self.sq_3.NAOK)}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:165--&amp;gt;&lt;br /&gt;
The &#039;that&#039; variable is like the &#039;self&#039; variable, but lets you refer to other questions.  Its syntax is:&lt;br /&gt;
*that.&#039;&#039;qname&#039;&#039;&lt;br /&gt;
*that.&#039;&#039;qname&#039;&#039;.&#039;&#039;suffix&#039;&#039;&lt;br /&gt;
*that.&#039;&#039;qname&#039;&#039;.&#039;&#039;sub-selector&#039;&#039;&lt;br /&gt;
*that.&#039;&#039;qname&#039;&#039;.&#039;&#039;sub-selector&#039;&#039;.&#039;&#039;suffix&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:166--&amp;gt;&lt;br /&gt;
&#039;&#039;qname&#039;&#039; is the question name without any sub-question extensions.  So, say you create a question &#039;q1&#039;, that is its &#039;&#039;qname&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:167--&amp;gt;&lt;br /&gt;
Examples:&lt;br /&gt;
*Has any part of question q1 been answered?  {count(that.q1.NAOK)&amp;gt;0}&lt;br /&gt;
*What is the assessment score for q2?  {sum(that.q2.NAOK)}&lt;br /&gt;
*What is the grand total of q3? {sum(that.q3.NAOK)}&lt;br /&gt;
*What is the total of row C in q4?  {sum(that.q4.sq_C.NAOK)}&lt;br /&gt;
*What is the total of column 2 in q4? {sum(that.q4.sq_2.NAOK)}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:168--&amp;gt;&lt;br /&gt;
The &#039;self&#039; and &#039;that&#039; variables can be used in any relevance,  validation, or tailoring.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:169--&amp;gt;&lt;br /&gt;
The one caveat is that when you use the [[Show Logic File|Show Logic File]] feature, it will show you the expanded value of &#039;self&#039; and &#039;that&#039;.  This lets you see the actual equation that will be generated so that you (and Expression Manager) can validate that the variables exist.  This may seem confusing since you may see quite lenghty equations.  However, if you edit the question, you will see the original equation using &#039;self&#039; and/or &#039;that&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:170--&amp;gt;&lt;br /&gt;
Also note that you should not use these variables if (a) you want to explicitly name each variable used in an equation, or (b) use variables that do not have sub-questions (e.g. single response questions).  In those cases, prefixing a variable with &#039;that&#039; is overkill, and you run the risk of getting unexpected results.&lt;br /&gt;
&lt;br /&gt;
==Usage of NAOK== &amp;lt;!--T:218--&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:219--&amp;gt;&lt;br /&gt;
NAOK --&amp;gt; Not Available / Ok&lt;br /&gt;
&lt;br /&gt;
When you put some variable from question in any equation : if this question (or subquestion) is hidden by condition : this disable all equation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:220--&amp;gt;&lt;br /&gt;
For example : count(Q1_SQ1,Q1_SQ2,Q1_SQ3,Q1_SQ4) give always an empty string if one subquestion of Q1 is filtered.&lt;br /&gt;
To count the number of checked subquestion in such question can be count(Q1_SQ1.NAOK,Q1_SQ2.NAOK,Q1_SQ3.NAOK,Q1_SQ4.NAOK). If the sub question is hidden :Expression manager return an empty string.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:221--&amp;gt;&lt;br /&gt;
Without NAOK : if one question or one subquestion is hidden : Expression Manager return always an empty string, same to return false.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:222--&amp;gt;&lt;br /&gt;
The .shown always use the NAOK system (empty string if hidden) but if you need the code of the answer : it&#039;s always a good idea to add .NAOK after the question code. Except if you need it and know what you do.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:223--&amp;gt;&lt;br /&gt;
Another example and information is provided at [[#Overriding_Cascading_Conditions|Overriding Cascading Conditions]]&lt;br /&gt;
&lt;br /&gt;
==Access to Functions== &amp;lt;!--T:171--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:172--&amp;gt;&lt;br /&gt;
Expression Manager provides access to mathematical, string, and user-defined functions, as shown below.  It has PHP and JavaScript equivalents for these functions so that they work identically on server-side (PHP) and client-side (JavaScript).  It is easy to add new functions.&lt;br /&gt;
&lt;br /&gt;
===Implemented Functions=== &amp;lt;!--T:173--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:174--&amp;gt;&lt;br /&gt;
The following functions are currently available:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:175--&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Function!!Meaning!!Syntax&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.abs.php abs]||Absolute value||number abs(number)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.acos.php acos]||Arc cosine||number acos(number)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.addslashes.php addslashes]||Quote string with slashes||string addslashes(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.asin.php asin]||Arc sine||number asin(number)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.atan.php atan]||Arc tangent||number atan(number)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.atan2.php atan2]||Arc tangent of two variables||number atan2(number, number)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.ceil.php ceil]||Round fractions up||number ceil(number)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.checkdate.php checkdate]||Returns true(1) if it is a valid date in gregorian calendar||bool checkdate(month,day,year)&lt;br /&gt;
|-&lt;br /&gt;
|convert_value||Convert a numerical value using a inputTable and outputTable of numerical values||number convert_value(fValue, iStrict, sTranslateFromList, sTranslateToList)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.cos.php cos]||Cosine||number cos(number)&lt;br /&gt;
|-&lt;br /&gt;
|count||count the number of answered (non-blank)questions in the list||number count(arg1, arg12, ..., argN)&lt;br /&gt;
|-&lt;br /&gt;
|countif||Count the number of answered questions in the list equal the first argument||number countif(matches, arg1, arg2, ... argN)&lt;br /&gt;
|-&lt;br /&gt;
|countifop||Count the number of answered questions in the list which pass the criteria (arg op value)||number countifop(op, value, arg1, arg2, ... argN)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.date.php date]||Format a local date/time||string date(format &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;, timestamp=time()])&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.exp.php exp]||Calculates the exponent of e||number exp(number)&lt;br /&gt;
|-&lt;br /&gt;
|fixnum||Display numbers with comma as radix separator, if needed||string fixnum(number)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.floor.php floor]||Round fractions down||number floor(number)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.gmdate.php gmdate]||Format a GMT date/time||string gmdate(format &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;, timestamp=time()])&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.html-entity-decode.php html_entity_decode]||Convert all HTML entities to their applicable characters (always uses ENT_QUOTES and UTF-8)||string html_entity_decode(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.htmlentities.php htmlentities]||Convert all applicable characters to HTML entities (always uses ENT_QUOTES and UTF-8)||string htmlentities(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.htmlspecialchars.php expr_mgr_htmlspecialchars]||Convert special characters to HTML entities (always uses ENT_QUOTES and UTF-8)||string htmlspecialchars(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.htmlspecialchars-decode.php expr_mgr_htmlspecialchars_decode]||Convert special HTML entities back to characters (always uses ENT_QUOTES and UTF-8)||string htmlspecialchars_decode(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.idate.php idate]||Format a local time/date as integer||string idate(string &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;, timestamp=time()])&lt;br /&gt;
|-&lt;br /&gt;
|if||Excel-style if(test,result_if_true,result_if_false)||if(test,result_if_true,result_if_false)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.implode.php implode]||Join array elements with a string||string implode(glue,arg1,arg2,...,argN)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.intval.php intval]||Get the integer value of a variable||int intval(number &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;, base=10])&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.empty.php is_empty]||Determine whether a variable is considered to be empty||bool is_empty(var)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.is-float.php is_float]||Finds whether the type of a variable is float||bool is_float(var)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.is-int.php is_int]||Find whether the type of a variable is integer||bool is_int(var)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.is-nan.php is_nan]||Finds whether a value is not a number||bool is_nan(var)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.is-null.php is_null]||Finds whether a variable is NULL||bool is_null(var)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.is-numeric.php is_numeric]||Finds whether a variable is a number or a numeric string||bool is_numeric(var)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.is-string.php is_string]||Find whether the type of a variable is string||bool is_string(var)&lt;br /&gt;
|-&lt;br /&gt;
|join{{NewIn|2.0|b=130129}}||Join elements as a new string||join(arg1, arg2, ... argN)&lt;br /&gt;
|-&lt;br /&gt;
|list||Return comma-separated list of non-blank values||string list(arg1, arg2, ... argN)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.log.php log]|| The logarithm of number to base, if given, or the natural logarithm. ||number log(number,base=e)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.ltrim.php ltrim]||Strip whitespace (or other characters) from the beginning of a string||string ltrim(string &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;, charlist])&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.max.php max]||Find highest value||number max(arg1, arg2, ... argN)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.min.php min]||Find lowest value||number min(arg1, arg2, ... argN)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.mktime.php mktime]||Get UNIX timestamp for a date (each of the 6 arguments are optional)||number mktime([hour [, minute [, second [, month [, day [, year ]]]]]])&lt;br /&gt;
|-&lt;br /&gt;
|modulo-function||The modulo function is &#039;&#039;&#039;not supported&#039;&#039;&#039; yet. You can use the floor() function instead||floor(x/y)==(x/y)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.nl2br.php nl2br]||Inserts HTML line breaks before all newlines in a string||string nl2br(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.number-format.php number_format]||Format a number with grouped thousands||string number_format(number)&lt;br /&gt;
|-&lt;br /&gt;
|pi||Get value of pi||number pi()&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.pow.php pow]||Exponential expression||number pow(base, exp)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.quoted-printable-decode.php quoted_printable_decode]||Convert a quoted-printable string to an 8 bit string||string quoted_printable_decode(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.quoted-printable-encode.php quoted_printable_encode]||Convert a 8 bit string to a quoted-printable string||string quoted_printable_encode(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.quotemeta.php quotemeta]||Quote meta characters||string quotemeta(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.rand.php rand]||Generate a random integer, see [[Expression Manager Sample Surveys#Randomly Ask One Question Per Group|this example]]||int rand() OR int rand(min, max)&lt;br /&gt;
|-&lt;br /&gt;
|regexMatch||compare a string to a [[Using regular expressions|regular expression]]||bool regexMatch(pattern,input)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.round.php round]||Rounds a number to an optional precision||number round(val &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;, precision])&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.rtrim.php rtrim]||Strip whitespace (or other characters) from the end of a string||string rtrim(string &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;, charlist])&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.sin.php sin]||Sine||number sin(arg)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.sprintf.php sprintf]||Return a formatted string||string sprintf(format, arg1, arg2, ... argN)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.sqrt.php sqrt]||Square root||number sqrt(arg)&lt;br /&gt;
|-&lt;br /&gt;
|stddev||Calculate the Sample Standard Deviation for the list of numbers||number stddev(arg1, arg2, ... argN)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.str-pad.php str_pad]||Pad a string to a certain length with another string||string str_pad(input, pad_length &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;, pad_string])&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.str-repeat.php str_repeat]||Repeat a string||string str_repeat(input, multiplier)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.str-replace.php str_replace]||Replace all occurrences of the search string with the replacement string||string str_replace(search, replace, subject)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.strcasecmp.php strcasecmp]||Binary safe case-insensitive string comparison||int strcasecmp(str1, str2)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.strcmp.php strcmp]||Binary safe string comparison||int strcmp(str1, str2)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.strip-tags.php strip_tags]||Strip HTML and PHP tags from a string||string strip_tags(str, allowable_tags)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.stripos.php stripos]||Find position of first occurrence of a case-insensitive unicode string (starting by 0, return false if not found)|||int stripos(haystack, needle &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;, offset=0])&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.stripslashes.php stripslashes]||Un-quotes a quoted string||string stripslashes(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.stristr.php stristr]||Case-insensitive strstr||string stristr(haystack, needle &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;, before_needle=false])&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.strlen.php strlen]||Get string length||int strlen(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.strpos.php strpos]||Find position of first occurrence of an unicode string (starting by 0, return false if not found)||int strpos(haystack, needle &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt; offset=0])&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.strrev.php strrev]||Reverse a string||string strrev(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.strstr.php strstr]||Find first occurrence of a string||string strstr(haystack, needle&amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;, before_needle=false])&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.strtolower.php strtolower]||Make a string lowercase||string strtolower(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.strtotime.php strtotime]||Parse about any English textual datetime description into a Unix timestamp||int strtotime(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.strtoupper.php strtoupper]||Make a string uppercase||string strtoupper(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.substr.php substr]||Return part of an unicode string||string substr(string, start &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;, length])&lt;br /&gt;
|-&lt;br /&gt;
|sum||Calculate the sum of values in an array||number sum(arg1, arg2, ... argN)&lt;br /&gt;
|-&lt;br /&gt;
|sumifop||Sum the values of answered questions in the list which pass the criteria (arg op value)||number sumifop(op, value, arg1, arg2, ... argN)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.tan.php tan]||Tangent||number tan(arg)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.time.php time]||Return current UNIX timestamp||number time()&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.trim.php trim]||Strip whitespace (or other characters) from the beginning and end of a string||string trim(string &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;, charlist])&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.ucwords.php ucwords]||Uppercase the first character of each word in a string||string ucwords(string)&lt;br /&gt;
|-&lt;br /&gt;
|unique||Returns true if all non-empty responses are unique||boolean unique(arg1, ..., argN)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Functions that are Planned or Being Considered=== &amp;lt;!--T:176--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:177--&amp;gt;&lt;br /&gt;
Other functions that are planned (or being considered) but which are not implemented yet include the following.  Some of these are for backwards compatability with another survey tool.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:178--&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Syntax!!Meaning!!Comments&lt;br /&gt;
|-&lt;br /&gt;
|e()||returns the value of e||&lt;br /&gt;
|-&lt;br /&gt;
|formatDate(X,PAT)||return the string value of date X formatted according to Java data format pattern PAT||&lt;br /&gt;
|-&lt;br /&gt;
|formatNumber(X,PAT)||return the string value of number X formatted according to Java number format pattern PAT||&lt;br /&gt;
|-&lt;br /&gt;
|getAnsOption(X)||returns the text corresponding to the selected option for answer X||this is the same as X.shown&lt;br /&gt;
|-&lt;br /&gt;
|getAnsOption(X,Y)||returns the text corresponding to the option at index Y of node X||&lt;br /&gt;
|-&lt;br /&gt;
|getRelevance(X)||returns the relevance equation for question X||&lt;br /&gt;
|-&lt;br /&gt;
|getStartTime()||returns the date corresponding to the system time when the interview was started||&lt;br /&gt;
|-&lt;br /&gt;
|getType(X)||returns the string name of the datatype - e.g. *NA* if isNA()||&lt;br /&gt;
|-&lt;br /&gt;
|gotoFirst()||jumps to the first relevant set of questions - this violates the normal flow of the system||&lt;br /&gt;
|-&lt;br /&gt;
|gotoNext()||jumps to the next set of relevant questions - this violates the normal flow of the system||&lt;br /&gt;
|-&lt;br /&gt;
|gotoPrevious()||jumps to the previous set of relevant questions - this violates the normal flow of the system||&lt;br /&gt;
|-&lt;br /&gt;
|isAsked(X)||returns true if the answer is neither *NA*, *INVALID*, nor *UNASKED*||&lt;br /&gt;
|-&lt;br /&gt;
|isInvalid(X)||returns true if the answer is of type *INVALID*||&lt;br /&gt;
|-&lt;br /&gt;
|isNA(X)||returns true if the answer is of type *NA*||&lt;br /&gt;
|-&lt;br /&gt;
|isNotUnderstood(X)||returns true if the answer if of type *HUH*||&lt;br /&gt;
|-&lt;br /&gt;
|isRefused(X)||returns true if the answer is of type *REFUSED*||&lt;br /&gt;
|-&lt;br /&gt;
|isSpecial(X)||returns true if the answer is of type *UNASKED*, *NA*, *REFUSED*, *INVALID*, *UNKNOWN*, or *HUH*||&lt;br /&gt;
|-&lt;br /&gt;
|isUnknown(X)||returns true if the answer is of type *UNKNOWN*||&lt;br /&gt;
|-&lt;br /&gt;
|jumpTo(X)||jump to the group containing the named question -- this violates the normal flow of the system||&lt;br /&gt;
|-&lt;br /&gt;
|jumpToFirstUnasked()||jump to the first unasked question &amp;lt;strike&amp;gt; thus bypassing previous answered questions &amp;lt;/strike&amp;gt; this violates the normal flow of the system||&lt;br /&gt;
|-&lt;br /&gt;
|lastIndexOf(X,Y)||returns the last index (base 0) of string Y in string X. Returns -1 if Y is not contained within X||&lt;br /&gt;
|-&lt;br /&gt;
|list(X,...)||a string containing a comma separated list of the positive values with &amp;quot;and&amp;quot; separating the last two||&lt;br /&gt;
|-&lt;br /&gt;
|mean(X,...)||returns the mean of a list of values||&lt;br /&gt;
|-&lt;br /&gt;
|numAnsOptions(X)||returns the number of answer options that question X has||&lt;br /&gt;
|-&lt;br /&gt;
|orlist(X,...)||a string containing a comma separated list of the positive values, with &amp;quot;or&amp;quot; separting the last two||&lt;br /&gt;
|-&lt;br /&gt;
|parseDate(X,PAT)||returns the date value of string X parsed with Java date format pattern PAT||&lt;br /&gt;
|-&lt;br /&gt;
|parseNumber(X,PAT)||returns the numerical value of string X parsed with Java number format pattern PAT||&lt;br /&gt;
|-&lt;br /&gt;
|showAllResponsesExcept( questionList,attributeList,attributeTitleList)||questionList = pipe-delimited list of question identifiers; attributeList = pipe-delimited list of attributes (like question#, title, text, type - so you can decide what to show); attributeTitleList = pipe-delimited list of table headers, so can internationalize the report.||&lt;br /&gt;
|-&lt;br /&gt;
|showTheseResponses( questionList,attributeList,attributeTitleList)||questionList = pipe-delimited list of question identifiers; attributeList = pipe-delimited list of attributes (like question#, title, text, type - so you can decide what to show); attributeTitleList = pipe-delimited list of table headers, so can internationalize the report.|| &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Expression Manager Knows Which Variables are Local== &amp;lt;!--T:179--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:180--&amp;gt;&lt;br /&gt;
In order to properly build the JavaScript for page, Expression Manager needs to know which variables are set on the page, and what their JavaScript ID is (e.g. for document.getElementById(x)).  It also must know which variables are set on other pages (so that it can ensure that the needed &amp;lt;input type=&#039;hidden&#039; value=&#039;x&#039;&amp;gt; fields are present and populated).&lt;br /&gt;
&lt;br /&gt;
==Cascading Conditions== &amp;lt;!--T:181--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:182--&amp;gt;&lt;br /&gt;
If any of the variables are irrelevant, the whole equation will be irrelevant (false).  For example, in the following table, N/A means that one of the variables was not relevant&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:183--&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Operator!!Example!!a!!b!!Result&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;+ (unary)&amp;lt;/nowiki&amp;gt;||&amp;lt;nowiki&amp;gt;+a&amp;lt;/nowiki&amp;gt;||N/A|| ||false&lt;br /&gt;
|-&lt;br /&gt;
|- (unary)||-a||N/A|| ||false&lt;br /&gt;
|-&lt;br /&gt;
|!||!a||N/A|| ||false&lt;br /&gt;
|-&lt;br /&gt;
|== (or eq)||a == b||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|== (or eq)||a == b||N/A||0||false&lt;br /&gt;
|-&lt;br /&gt;
|== (or eq)||a == b||N/A||N/A||false&lt;br /&gt;
|-&lt;br /&gt;
|!= (or ne)||a != b||N/A||5|| false&lt;br /&gt;
|-&lt;br /&gt;
|!= (or ne)||a != b||N/A||N/A|| false&lt;br /&gt;
|-&lt;br /&gt;
|!= (or ne)||a != b||N/A||0||false&lt;br /&gt;
|-&lt;br /&gt;
|&amp;gt; (or gt)||a &amp;gt; b||N/A||5|| false&lt;br /&gt;
|-&lt;br /&gt;
|&amp;gt;= (or ge)||a &amp;gt;= b||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt; (or lt)||a &amp;lt; b||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;= (or le)||a &amp;lt;= b||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|and||a and b||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|and||a and b||N/A||N/A||false&lt;br /&gt;
|-&lt;br /&gt;
|or||a or b||N/A||N/A||false&lt;br /&gt;
|-&lt;br /&gt;
|or||a or b||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;+&amp;lt;/nowiki&amp;gt;||a + b||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|-||a - b||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|*||a * b||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|/||a / b||5||N/A||false&lt;br /&gt;
|-&lt;br /&gt;
|()||(a)||N/A|| ||false&lt;br /&gt;
|-&lt;br /&gt;
|(exp)||(a &amp;amp;&amp;amp; b)||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|(exp) op (exp)||(b + b) &amp;gt; (a &amp;amp;&amp;amp; b)||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|function||sum(a,b,b)||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|function||max(a,b)||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|function||min(a,b)||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|function||implode(&#039;, &#039;,a,b,a,b)||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|function||if(a,a,b)||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|function||is_empty(a)||N/A|| ||false&lt;br /&gt;
|-&lt;br /&gt;
|function||is_empty(a)||0 (or blank)|| ||true&lt;br /&gt;
|-&lt;br /&gt;
|function||!is_empty(a)||N/A|| ||false&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Overriding Cascading Conditions=== &amp;lt;!--T:184--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:185--&amp;gt;&lt;br /&gt;
Say you want to show a running total of all relevant answers.  You might try to use the equation {sum(q1,q2,q3,...,qN)}.  However, this gets translated internally to LEMif(LEManyNA(&#039;q1&#039;,&#039;q2&#039;,&#039;q3&#039;,...,&#039;qN&#039;),&#039;&#039;,sum(LEMval(&#039;q1&#039;),LEMval(&#039;q2&#039;),LEMval(&#039;q3&#039;),...,LEMval(&#039;qN&#039;))).  So, if any of the values q1-qN are irrelevant, the equation will always return false.  In this case, the sum() will show 0 until all questions are answered.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:186--&amp;gt;&lt;br /&gt;
To get around this, each variable can have a &amp;quot;.NAOK&amp;quot; suffix (meaning that Not Applicable is OK) added to it.  In such cases, the following behavior occurs.  Say you have a variable q1.NAOK&lt;br /&gt;
#q1 is not added to the LEManyNA() clause&lt;br /&gt;
#LEMval(&#039;q1&#039;) will  continue to check whether the response is relevant, and will return &amp;lt;nowiki&amp;gt;&#039;&#039;&amp;lt;/nowiki&amp;gt; if it is not (so individual irrelevant responses will be ignored, but they will not void the entire expression).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:187--&amp;gt;&lt;br /&gt;
So, the solution to the running total problem is to use the equation sum(q1.NAOK,q2.NAOK,q3.NAOK,...,qN.NAOK).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:188--&amp;gt;&lt;br /&gt;
The use of the .NAOK suffix also lets authors design surveys that have several possible paths but then converge on common paths later.  For example, say subjects answer a survey in a way that is outside the normal range of responses.  The author could alert the subjects that they may not get valid results, and ask them whether they really want to  continue with the survey.  If they say Yes, then the rest of the questions will be shown.  The condition for the &amp;quot;rest of the questions&amp;quot; would check whether the initial responses were answered within the normal range OR whether the subject said Yes to the question that is only relevant if they answered outside the normal range.&lt;br /&gt;
&lt;br /&gt;
==How does Expression Manager Support Conditional Micro-Tailoring?== &amp;lt;!--T:189--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:190--&amp;gt;&lt;br /&gt;
Here is an example of micro-tailoring (where Question Type==&#039;expr&#039; means an Equation):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:191--&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Question Code!!Relevance!!Question Type!!Question&lt;br /&gt;
|-&lt;br /&gt;
|name||1||text||What is your name?&lt;br /&gt;
|-&lt;br /&gt;
|age||1||text||How old are you?&lt;br /&gt;
|-&lt;br /&gt;
|badage||!is_empty(age)||expr||{(age&amp;lt;16) or (age&amp;gt;80)}&lt;br /&gt;
|-&lt;br /&gt;
|agestop||badage||message||Sorry, {name}, you are too {if( (age&amp;lt;16),&#039;young&#039;,if( (age&amp;gt;80),&#039;old&#039;,&#039;middle-aged&#039;) ) } for this test.&lt;br /&gt;
|-&lt;br /&gt;
|kids||!badage||yesno||Do you have children?&lt;br /&gt;
|-&lt;br /&gt;
|parents||1||expr||{!badage &amp;amp;&amp;amp; kids==&#039;Y&#039;}&lt;br /&gt;
|-&lt;br /&gt;
|numKids||parents||text||How many children do you have?&lt;br /&gt;
|-&lt;br /&gt;
|kid1||parents &amp;amp;&amp;amp; numKids &amp;gt;= 1||text||How old is your first child?&lt;br /&gt;
|-&lt;br /&gt;
|kid2||parents &amp;amp;&amp;amp; numKids &amp;gt;= 2||text||How old is your second child?&lt;br /&gt;
|-&lt;br /&gt;
|kid3||parents &amp;amp;&amp;amp; numKids &amp;gt;= 3||text||How old is your third child?&lt;br /&gt;
|-&lt;br /&gt;
|kid4||parents &amp;amp;&amp;amp; numKids &amp;gt;= 4||text||How old is your fourth child?&lt;br /&gt;
|-&lt;br /&gt;
|kid5||parents &amp;amp;&amp;amp; numKids &amp;gt;= 5||text||How old is your fifth child?&lt;br /&gt;
|-&lt;br /&gt;
|sumage||1||expr||{sum(kid1.NAOK,kid2.NAOK,kid3.NAOK,kid4.NAOK,kid5.NAOK)}&lt;br /&gt;
|-&lt;br /&gt;
|report||parents||yesno||{name}, you said you are {age} and that you have {numKids}.  The sum of ages of your first {min(numKids,5)} kids is {sumage}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:192--&amp;gt;&lt;br /&gt;
All of these questions can be on a single page (e.g. in the same group), and only the relevant questions will display.  Moreover, as you enter the ages of children, the sum() expression in the last question will dynamically update on the page.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:193--&amp;gt;&lt;br /&gt;
Expression Manager provides this functionality by surrounding each expression with a named &amp;lt;span&amp;gt; element.  Every time a value changes, it recomputes the expression that should appear in that &amp;lt;span&amp;gt; element and regenerates the display.  You can have dozens, or even hundreds, of such tailored expressions on the same page, and the page will re-display all of them in a single screen refresh.&lt;br /&gt;
&lt;br /&gt;
==Mapping of LimeSurvey 1.91+ to Expression Manager Functionality== &amp;lt;!--T:194--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:195--&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Old Feature!!New Feature!!Comments&lt;br /&gt;
|-&lt;br /&gt;
|Conditions||Relevance||You can use very complex conditional equations, and access a broader range of variables&lt;br /&gt;
|-&lt;br /&gt;
|Assessments||Equation||Any assessment scores can be re-structured into an Equation. This both ensures that the score is written to the database, and also lets you see dynamic changes to the score value on the current page&lt;br /&gt;
|-&lt;br /&gt;
|Replacements||Expression Manager||The core engine takes the input string and treats everything within curly braces as an Expression - so it handles all historical replacements types.  To avoid messing up embedded JavaScript, Expression Manager only processes content between curly braces as long as (a)  there is no leading or trailing whitespace within the curly braces - e.g. {expr} is an expression, but { expr}, {expr }, and { expr } are not expressions.  Furthermore, Expression Manager does not process content within its own strings (e.g. {list(&#039;hi&#039;,&#039;there {braces}&#039;)} generates &amp;quot;hi there {braces}&amp;quot;).  It also ignores escaped curly braces (e.g. \{this is not an expression\})&lt;br /&gt;
|-&lt;br /&gt;
|Validation||Expression Manager||The plan is to take the current min/max Question Attributes and have Expression Manager process them.  That way the min/max values can be expressions themselves&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Syntax Highlighting= &amp;lt;!--T:196--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:197--&amp;gt;&lt;br /&gt;
To help with entering and validating expressions, EM provides syntax highlighting with the following features:&lt;br /&gt;
&lt;br /&gt;
==Types and Meanings of Syntax Highlighting== &amp;lt;!--T:198--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:199--&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Color!!Sample!!Meaning!!Tooltip!!Comments&lt;br /&gt;
|-&lt;br /&gt;
|tan background||style=&#039;background-color: #eee8aa&#039;|Sample||the whole equation||none||Anything within curly braces that is recognized as an equation (e.g. there is no leading or trailing whitepace) will be color-coded with a tan background to help distinguish it from surrounding text&lt;br /&gt;
|-&lt;br /&gt;
|bold red text||style=&#039;color:#ff0000; background-color:#eee8aa&#039;|&#039;&#039;&#039;Sample&#039;&#039;&#039;||An error||Some explanation on error||Can be an unknow variable or an error in function, .... Survey can be totally broken, this don&#039;t show to public user.&lt;br /&gt;
|-&lt;br /&gt;
|blue text||style=&#039;color:#0000ff; background-color:#eee8aa&#039;|Sample||function name||meaning and allowable syntax||function names, or things that should be functions since they are followed by an opening parenthesis, are presented in bold blue text.  Tooltips show the meaning and allowable syntax for the function.&lt;br /&gt;
|-&lt;br /&gt;
|grey text||style=&#039;color:#808080; background-color:#eee8aa&#039;|Sample||string||none||single and double-quoted strings are shown in grey text&lt;br /&gt;
|-&lt;br /&gt;
|cyan text||style=&#039;color:#4169e1; background-color:#eee8aa&#039;|Sample||variable set on the same page,||&amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;name or SGQA code]: question; value; answerList showing codes for each value||Any variable that is set on the same page to the current question is shown in cyan text, showning it can be updated in javascript.  The tooltip shows its name (if you used INSERTANS:xxx) or SGQA code (if you used the new naming system), the actual question, and its current value (or blank if not set).  If the question type expects responses from an enumerated value set, the mapping of the codes to display values is show.&lt;br /&gt;
|-&lt;br /&gt;
|green text||style=&#039;color:#008000; background-color:#eee8aa&#039;|Sample||variable set on a prior page||&amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;name or SGQA code]: question; value; answerList showing codes for each value||Any variable that is set on a prior page is shown in bold green text.  The tooltip shows its name (if you used INSERTANS:xxx) or SGQA code (if you used the new naming system), the actual question, and its current value (or blank if not set).  If the question type expects responses from an enumerated value set, the mapping of the codes to display values is show.&lt;br /&gt;
|-&lt;br /&gt;
|bold pink text||style=&#039;color:#9370db; background-color:#eee8aa&#039;|Sample||variable set on a later page &amp;lt;sup&amp;gt;in general : empty at survey start, but can be filled with index or move previous&amp;lt;/sup&amp;gt;||&amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;name or SGQA code]: question; value; answerList showing codes for each value||Any variable that is set on a prior page is shown in bold pink text.  These are erorrs since the variable is  being used before it is declareed.  The tooltip shows its name (if you used INSERTANS:xxx) or SGQA code (if you used the new naming system), the actual question, and its current value (or blank if not set).  If the question type expects responses from an enumerated value set, the mapping of the codes to display values is show.&lt;br /&gt;
|-&lt;br /&gt;
|bold tan text||style=&#039;color:#a0522d; background-color:#eee8aa&#039;|Sample||a lime replacement value||the value||Lime Replacement Strings (like {TOKEN:xxx}, {PRIVACY_MESSAGE}) are shown in bold tan text.  &lt;br /&gt;
|-&lt;br /&gt;
|red text||style=&#039;color:#ff4500; background-color:#eee8aa&#039;|Sample||assignment operator (=) ||warning message||If you use one of the assignment operator (=) that operator will be displayed in red text.  This is meant to help prevent accidental re-assignment of values when you really meant to check whether a == b instead of  setting the value of a = b.&lt;br /&gt;
|-&lt;br /&gt;
|normal black text||style=&#039;color:black; background-color:#eee8aa&#039;|Sample||punctuation||none||All other punctuation within the expression is shown as normal black text.&lt;br /&gt;
|-&lt;br /&gt;
|red-boxed text||a bold red line surrounds the error||syntax error||description of the error||Any detected syntax errors are shown by surrounding the error with a red box.  The tooltip shows the error.  Examples include unmatched parentheses, use of undefined functions, passing the wrong number of arguments to functions, poorly structured expressions (e.g. missing operators between variables), trying to assign a new value to a read-only variable, trying to assign values to non-variables, or using unsupported syntax.  Note that the syntax error dectection system may only report one error in an expression even if there are multiple errors; however, if any errors are detected, at least one error will be shown.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Additional Reading= &amp;lt;!--T:202--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==[[Expression Manager Sample Surveys|Expression Manager Sample Surveys]]== &amp;lt;!--T:203--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==[[Expression Manager HowTos|Use Cases and HowTos]]== &amp;lt;!--T:204--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==[[Expression Manager Examples|Step-by-Step Examples]].== &amp;lt;!--T:205--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==[[Expression Manager for developers|Reference for Developers]]== &amp;lt;!--T:206--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==[[Expression Manager Roadmap|RoadMap/Status/ToDo List]]== &amp;lt;!--T:207--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/translate&amp;gt;&lt;/div&gt;</summary>
		<author><name>LimeAJ</name></author>
	</entry>
	<entry>
		<id>https://www.limesurvey.org/manual/index.php?title=Question_signature&amp;diff=73847</id>
		<title>Question signature</title>
		<link rel="alternate" type="text/html" href="https://www.limesurvey.org/manual/index.php?title=Question_signature&amp;diff=73847"/>
		<updated>2017-06-29T17:29:25Z</updated>

		<summary type="html">&lt;p&gt;LimeAJ: added missing &amp;quot;by&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
=Question signature=&lt;br /&gt;
&lt;br /&gt;
Since question types can no longer be uniquely identified by their object names, we have created a signature scheme.&lt;br /&gt;
&lt;br /&gt;
While in a single limesurvey instance question objects must be uniquely named, there might be different plugins defining the question objects with the same name.&lt;br /&gt;
&lt;br /&gt;
To make sure we can identify what the type of a question is, we derive a unique identifier (GUID) from a signature.&lt;br /&gt;
&lt;br /&gt;
Each question object MUST therefore define a protected static $signature field. This field is used to derive the signature using a hashing approach.&lt;br /&gt;
&lt;br /&gt;
It is the developer&#039;s task to make this signature as unique as possible, yet, it MUST never change. If the signature of a question object changes it is recognized as a new question type, while this is not necessarily a problem, the fact that the old question type is no longer available is. Since LimeSurvey cannot find the old question type it will not be able to execute, import, or maybe even edit, surveys containing this now unknown question type.&lt;br /&gt;
&lt;br /&gt;
An example of a signature is shown below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
protected static $signature = array(&lt;br /&gt;
&lt;br /&gt;
   &#039;orignalAuthor&#039; =&amp;gt; &#039;Sam Mousa&#039;,&lt;br /&gt;
&lt;br /&gt;
   &#039;originalName&#039; =&amp;gt; &#039;Yes / No&#039;,&lt;br /&gt;
&lt;br /&gt;
   &#039;startDev&#039; =&amp;gt; &#039;2013-30-1&#039;&lt;br /&gt;
&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that you are free to use any format / data type you want. The GUID is derived using the following code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
* This function derives a unique identifier for identifying a question type.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
public static function getGUID()&lt;br /&gt;
&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
   // We use json_encode because it is faster than serialize.&lt;br /&gt;
&lt;br /&gt;
   return md5(json_encode(static::$signature));&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>LimeAJ</name></author>
	</entry>
	<entry>
		<id>https://www.limesurvey.org/manual/index.php?title=Expression_Manager&amp;diff=73692</id>
		<title>Expression Manager</title>
		<link rel="alternate" type="text/html" href="https://www.limesurvey.org/manual/index.php?title=Expression_Manager&amp;diff=73692"/>
		<updated>2017-06-07T13:40:03Z</updated>

		<summary type="html">&lt;p&gt;LimeAJ: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;languages /&amp;gt; &amp;lt;translate&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:1--&amp;gt;&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:2--&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;simplebox&amp;quot;&amp;gt; Note: This feature is only available in LimeSurvey 1.92 or later. &amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Quick Start Tutorial= &amp;lt;!--T:3--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Overview== &amp;lt;!--T:4--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:5--&amp;gt;&lt;br /&gt;
When customizing your surveys, you typically need a way to specify the following:&lt;br /&gt;
#&#039;&#039;&#039;Navigation/Branching&#039;&#039;&#039; - letting a subject&#039;s answers change the order in which questions are asked&lt;br /&gt;
#&#039;&#039;&#039;Tailoring/Piping&#039;&#039;&#039; - how to phrase the question (such as referring to prior answers, or conjugating sentences based upon the number or gender of your subjects), or how to generate custom reports (like assessment scores or tailored advice).&lt;br /&gt;
#&#039;&#039;&#039;Validation&#039;&#039;&#039; - ensuring that answers pass certain criteria, like min and max values, or matching an input pattern&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:6--&amp;gt;&lt;br /&gt;
Expression Manager (EM) provides an intuitive way to specifying the logic for each of those features.  Nearly anything that you can write as a standard mathematical equation is a valid expression, even if you are calling functions.  EM currently provides access to 70 functions, and can be easily extended to support more.  It also lets you access your variables using human-readable variable names (rather than SGQA names).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:7--&amp;gt;&lt;br /&gt;
The following sections show the main places where Expression Manager is used&lt;br /&gt;
&lt;br /&gt;
==Relevance (Controlling Navigation/Branching)== &amp;lt;!--T:8--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:9--&amp;gt;&lt;br /&gt;
Some surveys use &amp;quot;Goto Logic&amp;quot;, such that if you answer Question 1 with option C, then jump to Question 5. This approach is very limiting, since is hard to validate, and easily breaks if you have to re-order questions.  EM uses a Boolean relevance equation to specify all of the conditions under which a question might be valid.  If the question is relevant, then the question is asked, otherwise it is Not Applicable, and the value NULL is stored in the database.  This is similar to what can be done via the Conditions editor, but EM lets you easily specify much more complex and powerful criteria (and lets you use the variable name rather than SGQA naming).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:10--&amp;gt;&lt;br /&gt;
This image shows one way to review the relevance logic for a survey.  It computes Body Mass Index.  The relevance equation is shown in square bracket right after the variable name (which is in green).  So, the relevance of weight, weight_units, height and height_units are all 1, meaning that those questions are always asked.  However, the relevance for BMI is {!is_empty(height) and !is_empty(weight)}, which means that BMI will only be computed if the subject enters a value for both height and weight (thereby avoiding the risk of a divide by zero error).  Also, the Report question is only shown if the subject answers all four main questions (height, height_units, weight, weight_units).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:11--&amp;gt;&lt;br /&gt;
[[File:tutorial1.jpg]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:12--&amp;gt;&lt;br /&gt;
Relevance is shown and editable in the following places:&lt;br /&gt;
&lt;br /&gt;
===Viewing / Editing Question-Level Relevance=== &amp;lt;!--T:13--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:14--&amp;gt;&lt;br /&gt;
This equation computes the Body Mass Index (BMI).  It is only asked if the person first enters their height and weight.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:15--&amp;gt;&lt;br /&gt;
[[File:tutorial2.jpg]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:16--&amp;gt;&lt;br /&gt;
This is the edit screen for the BMI question.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:17--&amp;gt;&lt;br /&gt;
[[File:tutorial3.jpg]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:18--&amp;gt;&lt;br /&gt;
Note that you do not use the curly braces when you enter a Relevance Equation.&lt;br /&gt;
&lt;br /&gt;
===Viewing / Editing Group-Level Relevance=== &amp;lt;!--T:19--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:20--&amp;gt;&lt;br /&gt;
This is a sample census survey.  The first page asks how many people live with you and stores that in the &amp;quot;cohabs&amp;quot; variable.  This page is only shown if you have more than one cohabitant (so it is shown for the second person cohabitating with you), and also only shows if you specified how Person One is related to you (p1_rel).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:21--&amp;gt;&lt;br /&gt;
[[File:tutorial4.jpg]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:22--&amp;gt;&lt;br /&gt;
As you can see, the group also has question-level relevance criteria, such that each question only appears once you have answered the question before it (e.g. {!is_empty(p1_sex)}).  EM combines the Group and Question-level relevance for you.  Questions in a group are only asked  if the group as a whole is relevant.  Then, only the subset of questions within the group that are relevant are asked.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:23--&amp;gt;&lt;br /&gt;
Here is the screen for editing the group-level relevance for that question:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:24--&amp;gt;&lt;br /&gt;
[[File:tutorial5.jpg]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:25--&amp;gt;&lt;br /&gt;
Note that you do not use the curly braces when you enter a Relevance Equation.&lt;br /&gt;
&lt;br /&gt;
==Tailoring/Piping== &amp;lt;!--T:26--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:27--&amp;gt;&lt;br /&gt;
EM lets you easily do simple and complex conditional tailoring of your questions.  Sometimes you just need simple substitution, like saying, &amp;quot;You said you purchased &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;Product].  What did you like best about it?&amp;quot;.  Sometimes you need conditional substitution like &amp;quot;&amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;Mr./Mrs.] &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;LastName], would you be willing to complete our survey?&amp;quot;.  In this case,  you want to use Mr. or Mrs. based upon the person&#039;s gender.  Other times you need even more complex substitution (such as based upon a mathematical computation).  EM supports each of these types of tailoring/piping.&lt;br /&gt;
&lt;br /&gt;
===Conditional Equations=== &amp;lt;!--T:28--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:29--&amp;gt;&lt;br /&gt;
The Body Mass Index example shows the ability to compute a person&#039;s BMI, even while letting them enter their height in weight in metric or non-metric units.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:30--&amp;gt;&lt;br /&gt;
[[File:tailoring7.jpg]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:31--&amp;gt;&lt;br /&gt;
Here weight_kg is {if(weight_units == &#039;kg&#039;, weight, weight * .453592)}.  This if() function means that if the subject entered the weight using kilograms, use that value, otherwise multiple the entered value (which was in pounds) by .453592 to convert it to kilograms.  The height_m variable uses a similar approach to compute the person&#039;s height in meters, even if he entered his height in inches.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:32--&amp;gt;&lt;br /&gt;
BMI computes the weight formula as {weight_kg / (height_m * height_m)}.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:33--&amp;gt;&lt;br /&gt;
Lastly, the report conditionally tailors the message for the subject, telling him what he entered. (&amp;quot;You said you are 2 meters tall and weight 70 kg.&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:34--&amp;gt;&lt;br /&gt;
Although not well shown in the above image, weight_status uses nested if() statements to categorize the person as underweight to severely obese.  You can see its equation in the Show Logic View&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:35--&amp;gt;&lt;br /&gt;
[[File:tailoring8.jpg]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:36--&amp;gt;&lt;br /&gt;
From the edit window for this question, you can see two things:&lt;br /&gt;
#Tailoring must surround expressions with Curly Braces&lt;br /&gt;
#Expressions can span multiple lines if, as in this case, you want to make it easier to read the nested conditional logic.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:37--&amp;gt;&lt;br /&gt;
[[File:tailoring9.jpg]]&lt;br /&gt;
&lt;br /&gt;
===Tailored Questions, Answers, and Reports=== &amp;lt;!--T:38--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:39--&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;simplebox&amp;quot;&amp;gt;Note: Dynamic tailoring may not work if answer options are made available in select boxes on the same question page. This results from the fact that tailoring inserts a &amp;lt;nowiki&amp;gt;&amp;lt;span&amp;gt;&amp;lt;/nowiki&amp;gt; tag which is not valid inside select options.&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:40--&amp;gt;&lt;br /&gt;
This example shows the BMI report.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:41--&amp;gt;&lt;br /&gt;
[[File:tailoring10.jpg]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:42--&amp;gt;&lt;br /&gt;
Here is the edit window for the same question.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:43--&amp;gt;&lt;br /&gt;
[[File:tailoring11.jpg]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:44--&amp;gt;&lt;br /&gt;
As you can see, anything in curly braces is treated as an expression, so is syntax-highlighted (color coded) in the prior image.  If you had any typos (such as misspelled or undefined variable names or functions), EM would show an error, such as this, showing that height_unit is an undefined variable name (it is actually height_units), and rnd() is an undefined function (the proper function name is round()).  In both cases, the errors are surrounded by a red box to make it easier to spot and fix them.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:45--&amp;gt;&lt;br /&gt;
[[File:tailoring12.jpg]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:46--&amp;gt;&lt;br /&gt;
You can also see that you can quickly create complex reports, such as a table of entered values or tailored advice.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:47--&amp;gt;&lt;br /&gt;
Please remember that all tailoring must surround expressions with Curly Braces, so that LimeSurvey knows which parts of the question are free text and which should be parsed through Expression Manager.&lt;br /&gt;
&lt;br /&gt;
==Validation== &amp;lt;!--T:48--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:49--&amp;gt;&lt;br /&gt;
EM controls how most of the advanced question options work.  These control aspects like min/max numbers of answers; min/max individual values; min/max sum values; and checking that entered values match specified string patterns.  You continue to enter those advanced question options as usual.  However, now any value in one of those fields is considered an expression, so you can have min/max criteria with complex conditional relationships to other questions.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:50--&amp;gt;&lt;br /&gt;
In all of these cases, since the advanced question option is always considered an expression, you do not use curly braces when specifying it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:51--&amp;gt;&lt;br /&gt;
The [[Expression Manager Sample Surveys|Sample Surveys]] pages shows many working examples of using expressions for validations.&lt;br /&gt;
&lt;br /&gt;
=Introduction= &amp;lt;!--T:52--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:53--&amp;gt;&lt;br /&gt;
LimeSurvey uses the new Expression Manager (EM) module which will let LimeSurvey support more complex branching, assessments, validation, and tailoring.  It will replace how LimeSurvey manages Replacements, Conditions, and Assessments on the back-end.  It will also speed up processing considerably since it eliminates most run-time database reads.  EM was developed by Dr. Thomas White (TMSWhite).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:54--&amp;gt;&lt;br /&gt;
This wiki page is the definitive reference for Expression Manager syntax and functionality.&lt;br /&gt;
&lt;br /&gt;
==Key Definitions== &amp;lt;!--T:55--&amp;gt;&lt;br /&gt;
#&#039;&#039;&#039;Expression&#039;&#039;&#039;:  Anything surrounded by curly braces&lt;br /&gt;
#*As long as there is no white space immediately after the opening brace or before the closing curly brace&lt;br /&gt;
#*The contents of Expressions are evaluted by EM, so they can contain mathematical formulas, functions, and complex string and date processing.&lt;br /&gt;
#&#039;&#039;&#039;Tailoring&#039;&#039;&#039;: Sometimes called &amp;quot;piping&amp;quot;, this is the process of conditionally modifying text&lt;br /&gt;
#*You have access to all &#039;replacement fields&#039;, TOKENs, and INSERTANS values&lt;br /&gt;
#*You also have easier access to questions, answers, and their properties.&lt;br /&gt;
#&#039;&#039;&#039;Relevance&#039;&#039;&#039; Equation:  A new question attribute controlling question visiblity&lt;br /&gt;
#*If there is a relevance equation, then the question is only shown if the relevance evaluates to true.&lt;br /&gt;
#*Internally, all array_filter and array_filter_exclude commands become sub-question-level relevance&lt;br /&gt;
#&#039;&#039;&#039;Equation&#039;&#039;&#039; Question Type:  A new question type that saves calculations or reports to the database&lt;br /&gt;
#*It is like a Boilerplate question, but its contents are saved to the database even if you set &amp;quot;Always Hide this Question&amp;quot;&lt;br /&gt;
#&#039;&#039;&#039;Question Code&#039;&#039;&#039;:  This is the preferred variable name for EM&lt;br /&gt;
#*This can be a descriptive name indicating the purpose of the question, making it easier to read complex logic&lt;br /&gt;
#*Valid question codes should NOT start with a number, so when using the question code to number your questions, simply use &amp;quot;q1&amp;quot;, or &amp;quot;q1a&amp;quot; or &amp;quot;g1q2&amp;quot;.&lt;br /&gt;
#*This is what currently becomes the variable name if you export data to SPSS or R, so if you do statistical analysis, you probably already made this unique.&lt;br /&gt;
&lt;br /&gt;
==Do I have to use EM?== &amp;lt;!--T:56--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:57--&amp;gt;&lt;br /&gt;
The short answer is No (but also yes).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:58--&amp;gt;&lt;br /&gt;
EM is fully backwards-compatible with existing surveys.  So, if you are happy to use Conditions and Assessments in the style that LimeSurvey used in versions &amp;lt;= 1.91+, you can continue to do so.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:59--&amp;gt;&lt;br /&gt;
However, EM completely replaces how LimeSurvey internally deals with Conditions.  Although you can still use the Conditions Editor to create and manage conditions, LimeSurvey 1.92 will convert those to the equivalent Relevance Equations.  As part of the upgrade, LimeSurvey 1.92 will auto-convert all existing Conditions to Relevance Equations.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:60--&amp;gt;&lt;br /&gt;
This should give you the best of both worlds - you can continue using LimeSurvey as you are used to, but will see the Relevance Equation equivalent so you can gradually migrate to Relevance Equations directly whenever you see fit.&lt;br /&gt;
&lt;br /&gt;
==Can I mix use of Conditions and Relevance?== &amp;lt;!--T:61--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:62--&amp;gt;&lt;br /&gt;
Yes. You can use the Conditions editor for some questions and the Relevance editor for others.  Conditions are auto-converted to Relevance when you save the question.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:63--&amp;gt;&lt;br /&gt;
Note, we assume that if you are using the Conditions editor, that you want those Conditions to over-write any manually entered Relevance equation.  So, if you have existing Conditions and want to manually edit the Relevance, please delete the Conditions for that question first.  Specifically, copy the generated relevance equation to a text editor, use the Conditions menu to delete all of the conditions for that question (which will also delete the relevance), then edit the question and paste the generated relevance equation from the text editor back into the relevance field for that question (and save the question).  If there is enough demand for deleting conditions without deleting the generated relevance equation, we could add a bulk conversion process.&lt;br /&gt;
&lt;br /&gt;
==How should I choose between Conditions and Relevance?== &amp;lt;!--T:64--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:65--&amp;gt;&lt;br /&gt;
Here is a list of pros and cons of each style:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:66--&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Style!!Pros!!Cons&lt;br /&gt;
|-&lt;br /&gt;
|Conditions||1. Nice GUI for creating simple conditions &amp;lt;br/&amp;gt;2. GUI well documented and understood by support team||1. Only supports simple comparisons and does not AND/OR conditions well &amp;lt;br/&amp;gt;2. Cascading conditions work erratically &amp;lt;br/&amp;gt;3. Slow - database intensive, so can slow down long surveys &amp;lt;br/&amp;gt;4. Some reported problems with re-loading conditions &amp;lt;br/&amp;gt;5. GUI doesn&#039;t scale well when there are dozens, hundreds, or thousands of questions &amp;lt;br/&amp;gt;6. May be slow to convert paper-based surveys since must use SGQA names &amp;lt;br/&amp;gt;7. Often need a programmer to custom-code logic needed for complex branching&lt;br /&gt;
|-&lt;br /&gt;
|Relevance||1. Supports very complex logic, including 80+ functions and math/string operators &amp;lt;br/&amp;gt;2. Perfect support for cascading logic &amp;lt;br/&amp;gt;3. Fast - no extra database calls, so supports 1000+ question surveys &amp;lt;br/&amp;gt;4. No problems with re-loading logic since does not require SGQA codes &amp;lt;br/&amp;gt;5. Syntax-highlighting scales to 1000+ question surveys &amp;lt;br/&amp;gt;6. Easy and fast to use for groups wanting to computerize existing paper-based suveys.  &amp;lt;br/&amp;gt;7. Easily supports semi-structured interviews and epidemiological surveys without needing a programmers||1. No GUI for simple conditions - use syntax-highlighting instead &amp;lt;br/&amp;gt;2. New, so support teams have not mastered EM yet.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:67--&amp;gt;&lt;br /&gt;
The bottom is that if you are happy with how LimeSurvey 1.91+ works, there is no reason to change what you do.&lt;br /&gt;
&lt;br /&gt;
==What are some other benefits of using EM?== &amp;lt;!--T:68--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:69--&amp;gt;&lt;br /&gt;
Here are some of the other reasons you might want to use EM.&lt;br /&gt;
#Calculations - you can create any calculation you can think of:&lt;br /&gt;
#*You have access to all common mathematical operators and functions&lt;br /&gt;
#*You have access to 70+ mathematical, date, and string processing functions&lt;br /&gt;
#*It is fairly easy for developers to add new functions if users need them&lt;br /&gt;
#Storing Calculations to Database&lt;br /&gt;
#*You can now compute simple and complex calculations and/or scale scores AND have them stored in the database without needing JavaScript.&lt;br /&gt;
#*You use the Equation question type to accomplish this.&lt;br /&gt;
#Assessments&lt;br /&gt;
#*You can now create assessments or scale scores from any question type, not just the subset that used to be supported&lt;br /&gt;
#*You can use Tailoring to show running or total assessment scores anywhere needed - even on the same page&lt;br /&gt;
#*You have more control over the reports generated based upon those assessment scores&lt;br /&gt;
#*You can store assessment scores in the database without needing JavaScript&lt;br /&gt;
#*You can hide assessment scores without needing JavaScript or CSS&lt;br /&gt;
#Replacement Fields&lt;br /&gt;
#*Instead of using {INSERTANS:SGQA}, you can just use the Question Code - this makes it easier to read and validate.&lt;br /&gt;
#*This also avoids the common need to edit questions to change the SGQA code to make everything work.&lt;br /&gt;
#Tailoring - you can conditionally display text based upon other values&lt;br /&gt;
#*Use the appropriate title for a subject, like (e.g. &amp;quot;Hello &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;Mr./Mrs.] Smith&amp;quot;)&lt;br /&gt;
#*Output gramatically correct sentences based when singular/plural matter:  (e.g. &amp;quot;You have 1 child&amp;quot; vs. &amp;quot;You have 2 children&amp;quot;)&lt;br /&gt;
#*Appropriately conjugate verbs and decline nouns based upon subject&#039;s gender and plurality.&lt;br /&gt;
#New Variable Attributes - you can access the following to do your tailoring:&lt;br /&gt;
#* (no suffix) -  an alias for qcode.code&lt;br /&gt;
#*.code - the selected response code for the question if it is relevant (otherwise blank), or the text value if it is not a coded question&lt;br /&gt;
#*.NAOK - same as .code, but can be part of calculations or lists even if irrelevant&lt;br /&gt;
#*.value - the assessment value for the question if it is relevant (otherwise blank), or the text value if it is not a coded question&lt;br /&gt;
#*.valueNAOK - same as .value, but can be part of calculations or lists even if irrelevant&lt;br /&gt;
#*.shown - the answer as displayed to the user (this is what {INSERTANS:xxx}  does)&lt;br /&gt;
#*.qid - the question ID&lt;br /&gt;
#*.gid - the group ID&lt;br /&gt;
#*.sgqa - the SGQA value for the question&lt;br /&gt;
#*.jsName - the correct javascript variable name for the question, regardless whether defined on this page or another&lt;br /&gt;
#*.qseq - the question sequence (starting from 0)&lt;br /&gt;
#*.gseq - the group sequence (starting from 0)&lt;br /&gt;
#*.mandatory - whether the question is mandatory (Y/N)&lt;br /&gt;
#*.question - the text of the question&lt;br /&gt;
#*.relevance - the relevance equation for the question&lt;br /&gt;
#*.grelevance - the relevance equation for the group&lt;br /&gt;
#*.relevanceStatus - whether or not the question is currently relevant (1 if true, 0 if false)&lt;br /&gt;
#*.type - the question type (the one character code)&lt;br /&gt;
#Dynamic On-Page Changes&lt;br /&gt;
#*All Relevance, Calculation, and Tailoring works dynamically on a page - so changes in values instantly update the page&lt;br /&gt;
#*So, you have questions dynamically appear/disappear based upon whether they are relevant&lt;br /&gt;
#*Questions are also dynamically tailored based upon responses on the page, so you can see running totals, tailored sentences and customized reports.&lt;br /&gt;
#New Data Entry Screen&lt;br /&gt;
#*In addition to using the current data-entry system, you can just use Survey-All-In-One.&lt;br /&gt;
#*This supports the on-page relevance and tailoring, so data entry clerks can quickly tab through and they will only have to enter the relevant responses&lt;br /&gt;
#*This can be critical if your data entry person needs to see the tailoring, which is also dynamic.&lt;br /&gt;
#Eliminates the need for most custom JavaScript&lt;br /&gt;
#*EM easily supports complicated computations, scoring, tailoring and conditional logic.&lt;br /&gt;
#*Some things will still need JavaScript (like custom layouts and conditionally hiding question sub-elements), but your JavaScript can use the EM functions so that you can access questions by their Qcode instead of SGQA, and access any of the question properties listed above.&lt;br /&gt;
&lt;br /&gt;
==What are some other helpful new features enabled by EM?== &amp;lt;!--T:70--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:71--&amp;gt;&lt;br /&gt;
Regardless of whether you continue to use the Conditions Editor or manually compose Relevance Equations, you get these additional benefits:&lt;br /&gt;
#You can create more complex validation criteria&lt;br /&gt;
#*All of the advanced question attribute (like max_answers, min_num_value_n, max_num_value) can use Expressions.  So, you min/max criteria can be easily adjusted based upon prior responses, even if they are on the same page.&lt;br /&gt;
#*EM also handles all regular-expression-based validation, so you can robustly combine preg and equation-based question attributes.&lt;br /&gt;
#Easy Re-ordering (or deleting) of Questions and Groups&lt;br /&gt;
#*Prior to version 1.92, you could not re-order questions or groups if LimeSurvey thought that such-re-ordering could break conditions in which they were used.  Similarly, you could not delete questions if any other questions depended upon them.&lt;br /&gt;
#*With EM&#039;s syntax highlighting, it is easy to see and validate whether you try to use questions before they are declared.  So, we now let you re-order or delete questions and groups whenever you like.  EM will update all of the syntax highlighting to show you potential errors.&lt;br /&gt;
#*The re-order questions view has been enhanced to help with such review.  It now shows the question&#039;s relevance equation and tailoring, so you can immediately see whether any variables become pink (meaning they are used before being declared).&lt;br /&gt;
#The Question/Group Navigation Index is always available and accurate&lt;br /&gt;
#*Prior to version 1.92, these indexes were not available if there were complex conditions&lt;br /&gt;
#*With EM, we can guarantee that they are accurate.&lt;br /&gt;
#*Subjects can even jump back, to a prior question, change the answer, then jump forward (or submit)&lt;br /&gt;
#**When jumping forwards, EM will re-validate all of the intervening questions/groups.&lt;br /&gt;
#**If any questions become irrelevant, they will be NULLed in the database so that your data is internally consistent&lt;br /&gt;
#**If any questions become relevant or newly fail mandatory or validation rules, EM will stop on that page and force the user to answer those questions before jumping to their final destination.&lt;br /&gt;
#Auto-conversion of Conditions to Relevance&lt;br /&gt;
#*When you upgrade your database, all existing surveys that have conditions will have relevance equations generated for them&lt;br /&gt;
#*Whenever you import a survey, relevance equations will be created as needed&lt;br /&gt;
#*Whenever you add, delete, or modify conditions, EM will generate the appropriate relevance equation.&lt;br /&gt;
#Convenient Syntax Highlighting&lt;br /&gt;
#*When EM shows the relevance equation, it will show the Qcode, even if you entered an SGQA code, as we assume this will be easier to read.&lt;br /&gt;
#*All variables are color coded to show whether they were declared before or after the current question (or before or after the current group).  This lets you quickly detect and fix cases where you try to use variables for relevance (including array_filter), tailoring, or validation equations prior to declaring them.&lt;br /&gt;
#*In addition, if you hover your mouse over the color-coded variable, you will see the most important metadata about that question.   This includes the Group Sequence #, Question Sequence #, Qcode, Text of the question, and all available answer choices (if it is a question type with enumerated answer choices).&lt;br /&gt;
#**The list of answer choices uses this syntax:  &#039;answers&#039;:{key:val, ... }.&lt;br /&gt;
#**&#039;&#039;key&#039;&#039; has the syntax &#039;&#039;&#039;&#039;scale~code&#039;&#039;&#039;&#039; where &#039;&#039;scale&#039;&#039; is the answer scale (e.g. for dual scale), and &#039;&#039;code&#039;&#039; is the answer code.&lt;br /&gt;
#**&#039;&#039;val&#039;&#039; has the syntax &#039;&#039;&#039;&#039;value~shown&#039;&#039;&#039;&#039; where &#039;&#039;value&#039;&#039; is the assessment value (if using assessments, otherwise &#039;&#039;code&#039;&#039;)(e.g. Qcode.value), and &#039;&#039;shown&#039;&#039; is the display value as seen by the subject (e.g. Qcode.shown)&lt;br /&gt;
#**This means that many surveys can use calculations without needing assessment mode.  If you have enumerated answer options  that are unique, non-decimal, and non-negative, you can simply do calculations on the Qcode.code values.&lt;br /&gt;
#Easy review of entire survey logic and content&lt;br /&gt;
#*There is a new Show Survey Logic feature that lets you see everything about the survey (or group or question) on a single page.&lt;br /&gt;
#*It shows the Group, Question, Sub-Question, and Answer-level details for the selected scope (survey vs. group vs. question)&lt;br /&gt;
#*It also shows the relevance, sub-question-level relevance (for array_filter and array_filter_exclude), and generated validation equation (for preg and any validation rules like min/max sum/number of values), and all non-blank question attributes.&lt;br /&gt;
#*Everything is syntax-highlighted so that you can see potential syntax errors (like unbalanced parentheses or use of variables before they were declared)&lt;br /&gt;
#*The syntax-highligting supports rapid navigation and editing of the survey.&lt;br /&gt;
#**If you click on a variable name, it opens a browser window (or tab) that shows you that question and lets you edit it.&lt;br /&gt;
#**If you click on a group name, it opens a browser window (or tab) showing the group-reorder view so that you can easily move questions around.&lt;br /&gt;
#**All of the question attributes are also syntax highlighted.  This lets you set and see expressions within advanced question options (like basing the max/min number/sum of values on an expression)&lt;br /&gt;
#*The EM author used similar view (a little cleaner) to let his collaborating Epidemiologists and Institutional Review Board validate and authorize surveys with thousands of questions in highly branched and tailored structured interviews&lt;br /&gt;
&lt;br /&gt;
==How Backwards Compatible is EM with 1.91+?== &amp;lt;!--T:72--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:73--&amp;gt;&lt;br /&gt;
LimeSurvey 1.92 is fully backwards-compatible with 1.91+ with one exception/caveat:  1.92 handles less-than / greater-than comparisons against empty values differently than 1.91+.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:74--&amp;gt;&lt;br /&gt;
One of the LimeSurvey demo surveys uses a set of conditions that translates to this relevance equation:  {(age &amp;lt; 16) or (age == 20) or ... or (age == 80)}. In LimeSurvey 1.91+, (age &amp;lt; 16) is FALSE when there is no answer (the value is blank).  However, in LimeSurey 1.92, (age &amp;lt; 16) is TRUE when there is no answer, since both PHP and JavaScript treat blank as 0 in mathematical comparisons.  Thus, 1.91+ would hide that question when age was unanswered, but 1.92 would show it.  We went to great pains to prevent this, but since we needed to have the Expressions generate identical results in PHP and JavaScript, there was no way to make 1.92 treat &amp;quot;&amp;quot; &amp;lt; 16 as FALSE.  Fortunately, there is an easy work-around for this.  If you want (age &amp;lt; 16) to be FALSE, then use this expression instead: {(!is_empty(age) and age &amp;lt; 16)}.  You can use the new [[Show Logic File|Survey Logic File]] view to quickly identify and fix any such comparisons in your survey.&lt;br /&gt;
&lt;br /&gt;
=Getting Started= &amp;lt;!--T:75--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:76--&amp;gt;&lt;br /&gt;
The best way to get started with EM is to:&lt;br /&gt;
*Install the latest stable version from http://www.limesurvey.org/en/download &lt;br /&gt;
*Import and explore the [[Expression Manager Sample Surveys|sample surveys]].&lt;br /&gt;
*Explore the [[Expression Manager HowTos|use cases and HowTos]] and [[Expression Manager Examples|step-by-step examples]].&lt;br /&gt;
*Explore the EM documentation (this page)&lt;br /&gt;
*Examine the built-in EM test suite&lt;br /&gt;
**From any survey, under tools, select the EM option&lt;br /&gt;
**Available Functions lists the 70+ functions and syntax&lt;br /&gt;
**Unit Tests of Isolated Expressions&lt;br /&gt;
***shows examples of using all EM functions and operators, and the PHP and JavaScript results&lt;br /&gt;
***note there are few functions that generate different results in the PHP and JavaScript versions, so this page lets you plan your EM logic accordingly.&lt;br /&gt;
&lt;br /&gt;
=What Functionality does Expression Manager Extend/Replace? (LimeSurvey &amp;lt;= 1.91+)= &amp;lt;!--T:77--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Conditions =&amp;gt; Relevance== &amp;lt;!--T:78--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:79--&amp;gt;&lt;br /&gt;
Conditions controlled which  questions are visible.  The general syntax was &#039;&#039;SGQA operator Value&#039;&#039;, like &#039;&#039;111X2X3 == &amp;quot;Y&amp;quot;&#039;&#039;.  Conditions could be ANDed or ORed together, but mixing ANDs and ORs was difficult.  The conditions themselves were stored in a separate table, and large portion of LimeSurvey&#039;s code was devoted to managing Conditions.  Because of extensive database access, processing large numbers of conditions could cause noticable performance problems.  Furthermore, once you had conditions assigned to questions or groups, you were often not allowed to re-order or delete them.&lt;br /&gt;
&lt;br /&gt;
==Assessments =&amp;gt; Equations and  Micro-Tailoring== &amp;lt;!--T:80--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:81--&amp;gt;&lt;br /&gt;
Assessments let users create scale scores from a collection of questions.  However, they could not dynamically change on the current page, and their values were not stored to the database.&lt;br /&gt;
&lt;br /&gt;
==Replacements =&amp;gt; Micro-Tailoring== &amp;lt;!--T:82--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:83--&amp;gt;&lt;br /&gt;
Users could tailor some messages and questions based  upon prior responses.  For example, a question might be, &#039;&#039;{TOKEN:FIRSTNAME}, you said {INSERTANS:111X3X4} was your favorite sport&#039;&#039;.  However, it was not possible to do conditional tailoring (like say &amp;quot;Mr.&amp;quot; or &amp;quot;Mrs.&amp;quot; depending upon the person&#039;s gender), or conjugate verbs or decline nouns without fancy JavaScript.  Authors could implement surveys that seemed to tailor questions, but it required separate questions for each permutation, and complex conditions to decide which questions to display.&lt;br /&gt;
&lt;br /&gt;
==Validation== &amp;lt;!--T:84--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:85--&amp;gt;&lt;br /&gt;
Question could be validated with Regular expressions, or minimum/maximum values, or let an SGQA response serve as the minimum or maximum value.  However, validations could not be based upon calculations of other variables without fancy JavaScript.&lt;br /&gt;
&lt;br /&gt;
==Equations== &amp;lt;!--T:86--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:87--&amp;gt;&lt;br /&gt;
Equations were not supported without fancy JavaScript.&lt;br /&gt;
&lt;br /&gt;
==Equation Question Type== &amp;lt;!--T:88--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:89--&amp;gt;&lt;br /&gt;
Equations could not be saved to the database (e.g. the final score for an assessment) without fancy JavaScript.&lt;br /&gt;
&lt;br /&gt;
=How Will Expression Manager Replace/Extend That Functionality?= &amp;lt;!--T:90--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:91--&amp;gt;&lt;br /&gt;
The Expression Manager is a new core module within LimeSurvey that makes it much easier to support the type of complex functionality that used to require custom JavaScript.  It is also replacing the way LimeSurvey currently manages Conditions and Assessments.&lt;br /&gt;
&lt;br /&gt;
==New Terminology When Referring to Expression Manager (EM)== &amp;lt;!--T:92--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:93--&amp;gt;&lt;br /&gt;
EM &amp;quot;thinks&amp;quot; of its functionality in the following terms:&lt;br /&gt;
*&#039;&#039;&#039;Relevance-based Branching&#039;&#039;&#039; - if a question is relevant, then ask it, otherwise don&#039;t (e.g. make it invisible, and mark it as NULL in the database).  There is a new Relevance field for all Question types, and also for each Group (so you can apply a set of conditions to an entire group without having to copy the same condition to each question, and/or combine group and question-level conditional logic).&lt;br /&gt;
*&#039;&#039;&#039;Tailoring&#039;&#039;&#039; - Once you know which questions should be asked, tailoring (sometimes called &#039;&#039;piping&#039;&#039;) specifies how the question should be asked. This lets you support not only simple subsitution (like {TOKEN:FIRSTNAME}), but also conjugation of verbs and declination of nouns based upon the gender or number of your subjects.  It also lets you change the message you deliver to a subject based upon whether they answered (or how they answered) other questions.&lt;br /&gt;
*&#039;&#039;&#039;Equations&#039;&#039;&#039; - EM adds a new question type called Equation which stores the result of an Expression.  These equations results are computed and written to the database, even if you hide them on the page.  Thus, they are useful for hidden scoring calculations, navigation based upon complex equations, assessments, and reports that should be generated and easily available within the database.&lt;br /&gt;
&lt;br /&gt;
===Relevance and Cascading Relevance=== &amp;lt;!--T:94--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:95--&amp;gt;&lt;br /&gt;
Every question type now has a Relevance option which controls whether the question is displayed.  EM processes each of the Relevance Equations in the order they should appear in the survey.  If the expression is true (or missing - to support legacy surveys), the question will be displayed. If it is not relevant, then the question will be hidden, and the value will be NULLed in the database.  If there are no relevant questions in a group, the entire group will be skipped.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:96--&amp;gt;&lt;br /&gt;
Moreover, if any of the variables within an expression is irrelevant, then the expression always evaluates to false.  This enables Cascading Relevance so that you do not have to write very long Relevance equations for each question.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:97--&amp;gt;&lt;br /&gt;
Say you have 5 questions Q1-Q5, and you only want to show Q2 if Q1 was answered, and Q3 if Q2 was answered, etc.  The relevance equations might be:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:98--&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Question Code!!Relevance!!Question&lt;br /&gt;
|-&lt;br /&gt;
|Q1||1||What is your name?&lt;br /&gt;
|-&lt;br /&gt;
|Q2||Q1||{Q1}, how old are you?&lt;br /&gt;
|-&lt;br /&gt;
|Q3||Q2||So, you are {Q2} years old.  Are you married?&lt;br /&gt;
|-&lt;br /&gt;
|Q4||Q3 == &amp;quot;Y&amp;quot;||{Q1}, how long have you been married?&lt;br /&gt;
|-&lt;br /&gt;
|Q5||Q4||How many children do you have, {Q1}?&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:99--&amp;gt;&lt;br /&gt;
The relevance calculations also work in JavaScript - so you could put all the above questions on one page and it would still work as expected.  In fact, EM totally replaces how EM processes Survey vs. Group vs. Question-at-a-time survey formats.  They now all use the exactly same navigation engine so they work identically regardless of survey style.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:100--&amp;gt;&lt;br /&gt;
As long as you are on the same page, any data you entered will still be there, just hidden.  So, if you enter some information, then choose an option that makes them irrelevant, then make them relevant again, your answers will still be available.  However, as soon as you move to a different page, all irrelevant responses will be lost to integrity of the dataset.&lt;br /&gt;
&lt;br /&gt;
===Group-Level Relevance=== &amp;lt;!--T:101--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:102--&amp;gt;&lt;br /&gt;
Expression Manager also supports group-level relevance.  This makes it easier to implement looping.   Say you want to collect information about up to 10 entities (such a products or people in a household), where you first determine how many entities need follow-up (such as by asking how many people live in a household, or having people check which products they like from a long list).  After knowning how many entities need follow-up, you can use Group-level relevance like {count &amp;gt;= 1}, {count &amp;gt;=2}, ... {count &amp;gt;= 10} for each of the 10 groups of follow-up questions.  Within each group, you can have question-level conditional logic (e.g. gender or age-specific follow-up questions for each subject).  The question and group-level relevance equations are ANDed together to determine which should be shown.&lt;br /&gt;
&lt;br /&gt;
===Tailoring / Piping=== &amp;lt;!--T:103--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:104--&amp;gt;&lt;br /&gt;
Anything within curly braces is now treated as an Expression (with one exception described below).  Expressions have acccess to all of the LimeReplacementFields, all of the variables (via several aliases), all typical equation operators (mathematical, logical, and comparison), and dozens of functions (that even work dynamically on the client-side).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:105--&amp;gt;&lt;br /&gt;
Using these equations, you can do things such as:&lt;br /&gt;
#Conditionally show tailored messages to the respondants based upon prior responses&lt;br /&gt;
#Create Assessments and show Assessment results (or conditionally branch or show messages) based upon those results, all without using the Assessments module itself&lt;br /&gt;
#Conjugate verbs and decline nouns within questions, answers, and reports.&lt;br /&gt;
#Show summaries of responses before the &amp;quot;Show your answers&amp;quot; page at the end of the survey&lt;br /&gt;
&lt;br /&gt;
===Equations=== &amp;lt;!--T:106--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:107--&amp;gt;&lt;br /&gt;
There is a new question type called  Equation.  It is like a Boilerplate questions, except that it stores the value of what is displayed in the database.  So, if the Equation Question text contains an Assessment computation, that value would be stored in the database in a variable that can be displayed within public or private statistics.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:108--&amp;gt;&lt;br /&gt;
This solves a common request for storing Assessment scores within the database&lt;br /&gt;
&lt;br /&gt;
==Syntax== &amp;lt;!--T:109--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:110--&amp;gt;&lt;br /&gt;
Anything contained within curly braces is now considered an Expression (with one exception:  there must be no leading or trailing whitespace - this is needed to ensure the Expression Manager does not try to process embedded JavaScript).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:111--&amp;gt;&lt;br /&gt;
Note, it is OK for expressions to span multiple lines, as long as there is no whitespace after the opening  curly brace or before the closing curly brace.  This is especially helpful for nested if() statements like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:112--&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;{if(is_empty(PFTotals),&lt;br /&gt;
 &#039;&#039;,&lt;br /&gt;
 if(PFTotals &amp;gt;= -5 &amp;amp;&amp;amp; PFTotals &amp;lt;= -4,&lt;br /&gt;
   &#039;Very Soft&#039;,&lt;br /&gt;
   if(PFTotals &amp;gt;= -3 &amp;amp;&amp;amp; PFTotals &amp;lt;= -2,&lt;br /&gt;
     &#039;Soft&#039;,&lt;br /&gt;
     if(PFTotals == -1,&lt;br /&gt;
       &#039;Somewhat Soft&#039;,&lt;br /&gt;
       if(PFTotals == 0,&lt;br /&gt;
         &#039;Moderate&#039;,&lt;br /&gt;
         if(PFTotals == 1,&lt;br /&gt;
           &#039;Somewhat Hard&#039;,&lt;br /&gt;
           if(PFTotals &amp;gt;= 2 &amp;amp;&amp;amp; PFTotals &amp;lt;= 3,&lt;br /&gt;
             &#039;Hard&#039;,&lt;br /&gt;
             if(PFTotals &amp;gt;= 4 &amp;amp;&amp;amp; PFTotals &amp;lt;= 5,&lt;br /&gt;
               &#039;Very Hard&#039;,&lt;br /&gt;
               &#039;&#039;&lt;br /&gt;
             )&lt;br /&gt;
           )&lt;br /&gt;
         )&lt;br /&gt;
       )&lt;br /&gt;
     )&lt;br /&gt;
   )&lt;br /&gt;
 )&lt;br /&gt;
)}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:138--&amp;gt;&lt;br /&gt;
&amp;lt;div id=&amp;quot;EMsyntax&amp;quot;&amp;gt;Expression Manager supports the following syntax:&amp;lt;/div&amp;gt;&lt;br /&gt;
*All standard mathematical operators (e.g. +,-,*,/,!)&lt;br /&gt;
*All standard comparison operators (e.g. &amp;lt;,&amp;lt;=,==,!=,&amp;gt;,&amp;gt;=, plus these equivalents:  lt,le,eq,ne,gt,ge)&lt;br /&gt;
*Parentheses (so you can group sub-expressions)&lt;br /&gt;
*Conditional operators (e.g. &amp;amp;&amp;amp;,| | and these equivalents: and,or)&lt;br /&gt;
*Single and double-quoted strings (which can each embed strings with the other quote type)&lt;br /&gt;
*Comma operator (so can have a list of expressions and just return the final result)&lt;br /&gt;
*Assignment operator (=)&lt;br /&gt;
*Pre-defined variables (to refer to questions, question attributes, and responses) - e.g. all of the SGQA codes&lt;br /&gt;
*Pre-defined functions (there are already 70+, and it is easy to add more)&lt;br /&gt;
&lt;br /&gt;
=== Operators === &amp;lt;!--T:211--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:139--&amp;gt;&lt;br /&gt;
EM syntax follows normal operator precedence:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:140--&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Level!!Operator(s)!!Description&lt;br /&gt;
|-&lt;br /&gt;
|1||()||parentheses for grouping or calling functions&lt;br /&gt;
|-&lt;br /&gt;
|2||! - +||unary operators: not, negation, unary-plus&lt;br /&gt;
|-&lt;br /&gt;
|3||* /||times, divide&lt;br /&gt;
|-&lt;br /&gt;
|4||+ -||plus, minus&lt;br /&gt;
|-&lt;br /&gt;
|5||&amp;lt; &amp;lt;= &amp;gt; &amp;gt;= lt le gt ge||relative comparisons&lt;br /&gt;
|-&lt;br /&gt;
|6||== != eq ne||equality comparisons&lt;br /&gt;
|-&lt;br /&gt;
|7||and||logical AND&lt;br /&gt;
|-&lt;br /&gt;
|8||or||logical OR&lt;br /&gt;
|-&lt;br /&gt;
|9||=||assignment operator&lt;br /&gt;
|-&lt;br /&gt;
|10||,||comma operator&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:141--&amp;gt;&lt;br /&gt;
Note, for consistency between JavaScript and PHP, the plus operator (+) does addition if both operands are numeric, but does concatenation if both parts are non-numeric strings.  However, we recommend using the join() function for concatenation, as that makes your intent more clear, and avoids unexpected results if you were expecting strings but got numbers instead (or vice versa).&lt;br /&gt;
&lt;br /&gt;
===Caution about using Assignment Operator (=)=== &amp;lt;!--T:142--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:143--&amp;gt;&lt;br /&gt;
Note, you should avoid using the assignment operators unless absolutely necessary, since they may cause unexpected side-effects.  For example, if you change the value of a previous response, the cascading relevance and validation logic between that question and the current question is not re-computed, so you could end up with internally inconsistent data (e.g. questions that stay answered but should have been NULLed, or questions that are skipped but should have been answered).  In general, if you want to assign a value to a variable, you should create an Equation question type, and use an expression to set its value.  However, there are some rare times that people really need this operator, so we made it available.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:144--&amp;gt;&lt;br /&gt;
To help caution you about this operator, it is shown in red font within the syntax equations (so that you don&#039;t confuse it with &amp;quot;==&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
===Using Assignment Operator=== &amp;lt;!--T:145--&amp;gt;&lt;br /&gt;
The main reasons you may want to use assignment are:&lt;br /&gt;
*You need to set the default value for a question that does not accept defaults via equation (such as list radio, where the user interface lets you pick one of the answer options, but does not let you enter an equation).  However, be careful, as LimeSurvey will not be able to validate that your equation generates one of the allowable answers for that question.&lt;br /&gt;
*You need to forcibly change the response to a previous question based upon a later response&lt;br /&gt;
* etc...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:212--&amp;gt;&lt;br /&gt;
You can use all expression manager system for this purpose. It&#039;s better to use an [[Question_type_-_Equation|Equation question]] type to this purpose.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:213--&amp;gt;&lt;br /&gt;
Some example:&lt;br /&gt;
* Set answer to a short text question in lowercase : &amp;lt;code&amp;gt;{QCODE=strtolower(QCODE.NAOK)}&amp;lt;/code&amp;gt;&lt;br /&gt;
* Set a default answer to an array question type at start of a survey : &amp;lt;code&amp;gt;{Q1_SQ1=(is_empty(Q1_SQ1.NAOK),&amp;quot;A99&amp;quot;,Q1_SQ1.NAOK)}&amp;lt;/code&amp;gt;&lt;br /&gt;
* Set a default answer to an array texts question type at start of a survey : &amp;lt;code&amp;gt;{Q1_SQY1_SQX1 = (is_empty(Q1_SQY1_SQX1.NAOK),&amp;quot;Inserted answer&amp;quot;, Q1_SQY1_SQX1.NAOK)}&amp;lt;/code&amp;gt;&lt;br /&gt;
* Set an answer with condition : &amp;lt;code&amp;gt;{QCODE=if(YesNo=&amp;quot;Y&amp;quot;,&amp;quot;A1&amp;quot;,&amp;quot;&amp;quot;)}&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== XSS security == &amp;lt;!--T:214--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:215--&amp;gt;&lt;br /&gt;
With XSS enable, some expression manager system can not be used : &lt;br /&gt;
* starting a HTML tag in expression but ending in another expression&lt;br /&gt;
* use a complex expression in URL. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:216--&amp;gt;&lt;br /&gt;
Example and workaround&lt;br /&gt;
* &amp;lt;code&amp;gt;{if( 1 ,&amp;quot;&amp;amp;lt;strong&amp;amp;gt;&amp;quot;,&amp;quot;&amp;quot;)}information{if( 1 ,&amp;quot;&amp;amp;lt;/strong&amp;amp;gt;&amp;quot;,&amp;quot;&amp;quot;)}&amp;lt;/code&amp;gt; is broken with XSS security, here you can use &amp;lt;code&amp;gt;{if(1,&amp;quot;&amp;lt;strong&amp;amp;gt;information&amp;amp;lt;/strong&amp;amp;gt;&amp;quot;,&amp;quot;information&amp;quot;)}&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;&amp;amp;lt;a href=&amp;quot;/script.php?value={if(QCODE == &amp;quot;Y&amp;quot;,&amp;quot;yes&amp;quot;,&amp;quot;no&amp;quot;)}&amp;quot;&amp;amp;gt;next&amp;amp;lt;/a&amp;amp;gt;&amp;lt;/code&amp;gt;, here you can use an equation question because using a complete question code is OK : &amp;lt;code&amp;gt;&amp;amp;lt;a href=&amp;quot;/script.php?value={EQUATION.NAOK}&amp;quot;&amp;amp;gt;next&amp;amp;lt;/a&amp;amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Access to Variables== &amp;lt;!--T:146--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:147--&amp;gt;&lt;br /&gt;
Expression Manager provides read-only access to whichever variables we might need.  For backwards compatibility, it provides access to the following:&lt;br /&gt;
*TOKEN:xxx - the value of a TOKEN (e.g. TOKEN:FIRSTNAME, TOKEN:ATTRIBUTE_5) (Only for NOT anonymous survey).&lt;br /&gt;
*[[Adding a question#Information_from_previous_answers|INSERTANS:SGQA]] - the display value of an answer (e.g. &amp;quot;Yes&amp;quot;). For Expression Manager it&#039;s the same that using {QCODE.shown}.&lt;br /&gt;
*All [[The_template_editor#Keywords|{XXX} values used by templates]].&lt;br /&gt;
*In question text, you can use {QID} replaced by the question id and {SGQ} replaced by the SGQA of the question&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:148--&amp;gt;&lt;br /&gt;
In addition, Expression Manager lets you refer to variables by the Question Code (the &#039;title&#039; column in the questions table within the database).  This is also the variable label used when you export your data to SPSS, R, or SAS.  For example, if you have questions about name, age, and gender, you could call those variables &#039;&#039;name&#039;&#039;, &#039;&#039;age&#039;&#039;, and &#039;&#039;gender&#039;&#039; instead of &#039;&#039;12345X13X22&#039;&#039;, &#039;&#039;12345X13X23&#039;&#039;, and  &#039;&#039;12345X13X24&#039;&#039;.  This makes equations easier for everyone to read and validate the logic, plus makes it possible to shuffle questions around without having to keep track of group or question numbers.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:210--&amp;gt;&lt;br /&gt;
&amp;lt;div class=&#039;simplebox&#039;&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Important:&#039;&#039;&#039; It is only safe to refer to variables that occur in preceding pages or questions.&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:149--&amp;gt;&lt;br /&gt;
Furthermore, Expression Manager lets you access many properties of the Question:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:150--&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Syntax!!Meaning!!Example!!Example Result&lt;br /&gt;
|-&lt;br /&gt;
|Qcode||an alias for Qcode.code||{implode(&#039;,&#039;,name,gender)}||&#039;Tom&#039;,&#039;M&#039;&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.code||the selected response code for the question if it is relevant (otherwise blank), or the text value if it is not a coded question||{implode(&#039;,&#039;,name.code,gender.code)}||&#039;Tom&#039;,&#039;M&#039;&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.NAOK||same as Qcode - see discussion of NAOK||{gender.NAOK}||&#039;M&#039;&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.value||the assessment value for the question if it is relevant (otherwise blank), or the text value if it is not a coded question||{gender.value}||&#039;1&#039;&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.valueNAOK||same as Qcode.value - see discussion about NAOK||{gender.valueNAOK}||&#039;1&#039;&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.shown||the dispay value for the question||{implode(&#039;,&#039;,name.shown,gender.shown)}||&#039;Tom&#039;,&#039;Male&#039;&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.question||the text of the question||{gender.question}||&#039;What is your gender?&#039;&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.mandatory||whether the question is mandatory (Y/N)||{gender.mandatory}||&#039;N&#039;&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.qid||the internal question number (not the sequential number)||{gender.qid}||337&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.type||the question type||{gender.type}||&#039;G&#039;&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.jsName||the correct javascript name for the question, regardless whether declared on or off this page||{gender.jsName}||&#039;java1827X3X337&#039;&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.gid||the internal group number (not the sequential number)||{gender.gid}||3&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.qseq||the sequential number of the question, starting from 0||{gender.qseq}||5&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.gseq||the sequential number of the group, starting from 0||{gender.gseq}||1&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.relevanceStatus||whether the question is currently relevant (0 or 1)||{gender.relevanceStatus}||1&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.relevance||the question-level relevance equation||{gender.relevance}||&#039;!is_empty(name)&#039;&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.grelevance||the  group-level relevance equation||{gender.grelevance}||&#039;num_children &amp;gt;= 5&#039;&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.sgqa||the SGQA value for this question||{gender.sgqa}||&#039;1827X3X337&#039;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== HTML editor issue=== &amp;lt;!--T:151--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:217--&amp;gt;&lt;br /&gt;
{{Alert|This issue is fixed after 2.05 build 140803}} &lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:152--&amp;gt;&lt;br /&gt;
If you use HTML editor, some characters are replaced by HTML entities.&lt;br /&gt;
* &amp;amp; by &amp;amp;amp;amp;&lt;br /&gt;
* &amp;lt; by &amp;amp;amp;lt;&lt;br /&gt;
* &amp;gt; by &amp;amp;amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:209--&amp;gt;&lt;br /&gt;
If you use HTML editor you need to use :&lt;br /&gt;
* and for &amp;amp;&lt;br /&gt;
* lt for &amp;lt;&lt;br /&gt;
* le for &amp;lt;=&lt;br /&gt;
* gt for &amp;gt;&lt;br /&gt;
* ge for &amp;gt;=&lt;br /&gt;
&lt;br /&gt;
==Qcode Variable Naming== &amp;lt;!--T:153--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:154--&amp;gt;&lt;br /&gt;
Here are the details of how to construct a Qcode (and access some properties) by question type.  In general, Qcodes are constructed as:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:155--&amp;gt;&lt;br /&gt;
  QuestionCode . &#039;_&#039; . SubQuestionID . &#039;_&#039; . ScaleId&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:208--&amp;gt;&lt;br /&gt;
For comment and other, question code are QuestionCode_comment and QuestionCode_other&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:156--&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Type!!Description!!Code!!SubQs!!Answer Options!!Scales!!Answer Code!!Answer Shown!!Relevance&lt;br /&gt;
|-&lt;br /&gt;
|5||5 Point Choice Radio-Buttons||Q1|| ||1-5|| ||{Q1}||{Q1.shown}||{Q1==3}&lt;br /&gt;
|-&lt;br /&gt;
|B||Array (10 Point Choice) Radio-Buttons||Q2||L1-L6||1-10|| ||{Q2_L2}||{Q2_L2.shown}||{Q2_L2==7}&lt;br /&gt;
|-&lt;br /&gt;
|A||Array (5 Point Choice) Radio-Buttons||Q3||1-5||1-5|| ||{Q3_1}||{Q3_1.shown}||{Q3_1&amp;gt;=3}&lt;br /&gt;
|-&lt;br /&gt;
|1||Array (Flexible Labels) Dual Scale||Q4||sq1-sq5||0:a1-a3||1:b1-b3||{Q4_sq1_0}||{Q4_sq1_1.shown}||{Q4_sq1_1==&#039;b2&#039;}&lt;br /&gt;
|-&lt;br /&gt;
|H||Array (Flexible) - Column Format||Q5||1-5||s,m,t|| ||{Q5_1}||{Q5_1.shown}||{Q5_1==&#039;s&#039;}&lt;br /&gt;
|-&lt;br /&gt;
|F||Array (Flexible) - Row Format||Q6||F1-F5||1-5|| ||{Q6_F3}||{Q6_F3.shown}||{Q6_F3==4}&lt;br /&gt;
|-&lt;br /&gt;
|E||Array (Increase/Same/Decrease) Radio-Buttons||Q7||1-7||I,S,D|| ||{Q7_4}||{Q7_4.shown}||{Q7_4==&#039;D&#039;}&lt;br /&gt;
|-&lt;br /&gt;
|:||Array (Multi Flexi) 1 To 10||Q8||ls1,todo,ls2||min,max,avg|| ||{Q8_ls1_max}||{Q8_ls2_avg.shown}||{Q8_ls2_min==7}&lt;br /&gt;
|-&lt;br /&gt;
|;||Array (Multi Flexi) Text||Q9||hp,st,sw||1st,2nd,3rd|| ||{Q9_hp_3rd}||{Q9_hp_3rd.shown}||{Q9_hp_3rd==&#039;Peter&#039;}&lt;br /&gt;
|-&lt;br /&gt;
|C||Array (Yes/Uncertain/No) Radio-Buttons||Q10||1-5||Y,N,U|| ||{Q10_1}||{Q10_1.shown}||{Q10_3==&#039;Y&#039;}&lt;br /&gt;
|-&lt;br /&gt;
|X||Boilerplate Question||Q11|| || || || ||{Q11.shown}||&lt;br /&gt;
|-&lt;br /&gt;
|D||Date||Q12|| || || ||{Q12}||{Q12.shown}||&lt;br /&gt;
|-&lt;br /&gt;
|*||Equation||Q13|| || || ||{Q13}||{Q13.shown}||{Q13&amp;gt;5}&lt;br /&gt;
|-&lt;br /&gt;
|~124~||File Upload (records number of files uploaded)||Q14|| || || ||{Q14}|| ||{Q14&amp;gt;0}&lt;br /&gt;
|-&lt;br /&gt;
|G||Gender Drop-Down List||Q15|| ||M,F|| ||{Q15}||{Q15.shown}||{Q15==&#039;M&#039;}&lt;br /&gt;
|-&lt;br /&gt;
|U||Huge Free Text||Q16|| || || ||{Q16}||{Q16.shown}||{strlen(Q16)&amp;gt;100}&lt;br /&gt;
|-&lt;br /&gt;
|I||Language Question||Q17|| || || ||{Q17}||{Q17.shown}||{Q17==&#039;en&#039;}&lt;br /&gt;
|-&lt;br /&gt;
|!||List - Dropdown||Q18|| ||1-5|| ||{Q18}||{Q18.shown}||{Q18==3}&lt;br /&gt;
|-&lt;br /&gt;
|L||List Drop-Down/Radio-Button List||Q19|| ||A-Z|| ||{Q19}||{Q19.shown}||{Q19==&#039;X&#039;}&lt;br /&gt;
|-&lt;br /&gt;
|O||List With Comment Drop-Down/Radio-Button List + Textarea||Q20|| ||A-F|| ||{Q20},{Q20comment}||{Q20.shown}||{Q20==&#039;B&#039;}&lt;br /&gt;
|-&lt;br /&gt;
|T||Long Free Text||Q21|| || || ||{Q21}||{Q21.shown}||{strstr(Q21,&#039;hello&#039;)&amp;gt;0}&lt;br /&gt;
|-&lt;br /&gt;
|M||Multiple Choice Checkbox||Q22||A-F, other|| || ||{Q22_E}, {Q22_other}||{Q22_E.shown}, {Q22_other}||{Q22_E==&#039;Y&#039;}&lt;br /&gt;
|-&lt;br /&gt;
|P||Multiple Choice With Comments Checkbox + Text||Q23||A-F|| || ||{Q23_D}, {Q23_Dcomment}||{Q23_D.shown}||{!is_empty(Q23)}&lt;br /&gt;
|-&lt;br /&gt;
|K||Multiple Numerical Question||Q24||self,mom,dad|| || ||{Q24_self}||{Q24_self.shown}||{Q24_self&amp;gt;30}&lt;br /&gt;
|-&lt;br /&gt;
|Q||Multiple Short Text||Q25||A-F|| || ||{Q25_B}||{Q25_B.shown}||{substr(Q25_B,1,1)==&#039;Q&#039;}&lt;br /&gt;
|-&lt;br /&gt;
|N||Numerical Question Type||Q26|| || || ||{Q26}||{Q26.shown}||{Q26 &amp;gt; 30}&lt;br /&gt;
|-&lt;br /&gt;
|R||Ranking Style||Q27||1-4|| || ||{Q27_1}||{Q27_1.shown}||{Q27_1==3}&lt;br /&gt;
|-&lt;br /&gt;
|S||Short Free Text||Q28|| || || ||{Q28}||{Q28.shown}||{Q28==&#039;mine&#039;}&lt;br /&gt;
|-&lt;br /&gt;
|Y||Yes/No Radio-Buttons||Q29|| || || ||{Q29}||{Q29.shown}||{Q29==&#039;Y&#039;}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==The reserved &#039;this&#039;, &#039;self&#039;, and &#039;that&#039; variables== &amp;lt;!--T:157--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:158--&amp;gt;&lt;br /&gt;
Quite often, you want to evalute all parts of a question, such as counting how many sub-questions have been answered, or summing the scores.  Other times, you want to process just certain rows or columns of a question (such as getting the row or column sums and storing them in the database).  These reserved variables make that process relatively painless.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:159--&amp;gt;&lt;br /&gt;
The &#039;this&#039; variable is used exclusively within the &amp;quot;Whole question validation equation&amp;quot; and &amp;quot;Sub-question validation equation&amp;quot; advanced question options.  It expands to the variable names of each of the cells within those questions.  So, if you want to make sure that each entry is greater than three, you would set the &amp;quot;Sub-question validation equation&amp;quot; to (this &amp;gt; 3).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:160--&amp;gt;&lt;br /&gt;
The &#039;self&#039; and &#039;that&#039; variable are more powerful, and serve as macros which are expanded prior to processing equations.  The syntax choices are:&lt;br /&gt;
*self&lt;br /&gt;
*self.&#039;&#039;suffix&#039;&#039;&lt;br /&gt;
*self.&#039;&#039;sub-selector&#039;&#039;&lt;br /&gt;
*self.&#039;&#039;sub-selector&#039;&#039;.&#039;&#039;suffix&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:161--&amp;gt;&lt;br /&gt;
&#039;&#039;suffix&#039;&#039; is any of the normal qcode suffixes (e.g. NAOK, value, shown)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:162--&amp;gt;&lt;br /&gt;
&#039;&#039;sub-selector&#039;&#039; is one of:&lt;br /&gt;
*comments - only subquestions that are comments (e.g. from multiple choice with comment and list with comment)&lt;br /&gt;
*nocomments - only subquestions that are not comments&lt;br /&gt;
*sq_X - where X is a row or column identifier.  Only sub-questions matching pattern X are selected. Note that search is done on complete code identifier, then sq_X match and include subquestions nX, X, Xn (e.g. if you use sq_1, subquestions a1, 1a, 1, 11 or 001 was included). Put attention at dual scale question type where subquestions code are QCODE_SQCODE_1 and QCODE_SQCODE_1 and to ranking question type where subquestions code are QCODE_1,QCODE_2 ....&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:163--&amp;gt;&lt;br /&gt;
Examples:&lt;br /&gt;
*Has any part of a question been answered?  {count(self.NAOK)&amp;gt;0}&lt;br /&gt;
*What is the assessment score for this question?  {sum(self.value)}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:164--&amp;gt;&lt;br /&gt;
You can also use these to get row and column totals.  Say you have a array of numbers with rows A-E and columns 1-5.&lt;br /&gt;
*What is the grand total?  {sum(self.NAOK)}&lt;br /&gt;
*What is the total of row B?  {sum(self.sq_B.NAOK)}&lt;br /&gt;
*What is the total of column 3? {sum(self.sq_3.NAOK)}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:165--&amp;gt;&lt;br /&gt;
The &#039;that&#039; variable is like the &#039;self&#039; variable, but lets you refer to other questions.  Its syntax is:&lt;br /&gt;
*that.&#039;&#039;qname&#039;&#039;&lt;br /&gt;
*that.&#039;&#039;qname&#039;&#039;.&#039;&#039;suffix&#039;&#039;&lt;br /&gt;
*that.&#039;&#039;qname&#039;&#039;.&#039;&#039;sub-selector&#039;&#039;&lt;br /&gt;
*that.&#039;&#039;qname&#039;&#039;.&#039;&#039;sub-selector&#039;&#039;.&#039;&#039;suffix&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:166--&amp;gt;&lt;br /&gt;
&#039;&#039;qname&#039;&#039; is the question name without any sub-question extensions.  So, say you create a question &#039;q1&#039;, that is its &#039;&#039;qname&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:167--&amp;gt;&lt;br /&gt;
Examples:&lt;br /&gt;
*Has any part of question q1 been answered?  {count(that.q1.NAOK)&amp;gt;0}&lt;br /&gt;
*What is the assessment score for q2?  {sum(that.q2.NAOK)}&lt;br /&gt;
*What is the grand total of q3? {sum(that.q3.NAOK)}&lt;br /&gt;
*What is the total of row C in q4?  {sum(that.q4.sq_C.NAOK)}&lt;br /&gt;
*What is the total of column 2 in q4? {sum(that.q4.sq_2.NAOK)}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:168--&amp;gt;&lt;br /&gt;
The &#039;self&#039; and &#039;that&#039; variables can be used in any relevance,  validation, or tailoring.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:169--&amp;gt;&lt;br /&gt;
The one caveat is that when you use the [[Show Logic File|Show Logic File]] feature, it will show you the expanded value of &#039;self&#039; and &#039;that&#039;.  This lets you see the actual equation that will be generated so that you (and Expression Manager) can validate that the variables exist.  This may seem confusing since you may see quite lenghty equations.  However, if you edit the question, you will see the original equation using &#039;self&#039; and/or &#039;that&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:170--&amp;gt;&lt;br /&gt;
Also note that you should not use these variables if (a) you want to explicitly name each variable used in an equation, or (b) use variables that do not have sub-questions (e.g. single response questions).  In those cases, prefixing a variable with &#039;that&#039; is overkill, and you run the risk of getting unexpected results.&lt;br /&gt;
&lt;br /&gt;
==Usage of NAOK== &amp;lt;!--T:218--&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:219--&amp;gt;&lt;br /&gt;
NAOK --&amp;gt; Not Available / Ok&lt;br /&gt;
When you put some variable from question in any equation : if this question (or subquestion) is hidden by condition : this disable all equation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:220--&amp;gt;&lt;br /&gt;
For example : count(Q1_SQ1,Q1_SQ2,Q1_SQ3,Q1_SQ4) give always an empty string if one subquestion of Q1 is filtered.&lt;br /&gt;
To count the number of checked subquestion in such question can be count(Q1_SQ1.NAOK,Q1_SQ2.NAOK,Q1_SQ3.NAOK,Q1_SQ4.NAOK). If the sub question is hidden :Expression manager return an empty string.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:221--&amp;gt;&lt;br /&gt;
Without NAOK : if one question or one subquestion is hidden : Expression Manager return always an empty string, same to return false.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:222--&amp;gt;&lt;br /&gt;
The .shown always use the NAOK system (empty string if hidden) but if you need the code of the answer : it&#039;s always a good idea to add .NAOK after the question code. Except if you need it and know what you do.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:223--&amp;gt;&lt;br /&gt;
Another example and information is provided at [[#Overriding_Cascading_Conditions|Overriding Cascading Conditions]]&lt;br /&gt;
&lt;br /&gt;
==Access to Functions== &amp;lt;!--T:171--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:172--&amp;gt;&lt;br /&gt;
Expression Manager provides access to mathematical, string, and user-defined functions, as shown below.  It has PHP and JavaScript equivalents for these functions so that they work identically on server-side (PHP) and client-side (JavaScript).  It is easy to add new functions.&lt;br /&gt;
&lt;br /&gt;
===Implemented Functions=== &amp;lt;!--T:173--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:174--&amp;gt;&lt;br /&gt;
The following functions are currently available:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:175--&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Function!!Meaning!!Syntax&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.abs.php abs]||Absolute value||number abs(number)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.acos.php acos]||Arc cosine||number acos(number)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.addslashes.php addslashes]||Quote string with slashes||string addslashes(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.asin.php asin]||Arc sine||number asin(number)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.atan.php atan]||Arc tangent||number atan(number)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.atan2.php atan2]||Arc tangent of two variables||number atan2(number, number)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.ceil.php ceil]||Round fractions up||number ceil(number)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.checkdate.php checkdate]||Returns true(1) if it is a valid date in gregorian calendar||bool checkdate(month,day,year)&lt;br /&gt;
|-&lt;br /&gt;
|convert_value||Convert a numerical value using a inputTable and outputTable of numerical values||number convert_value(fValue, iStrict, sTranslateFromList, sTranslateToList)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.cos.php cos]||Cosine||number cos(number)&lt;br /&gt;
|-&lt;br /&gt;
|count||count the number of answered (non-blank)questions in the list||number count(arg1, arg12, ..., argN)&lt;br /&gt;
|-&lt;br /&gt;
|countif||Count the number of answered questions in the list equal the first argument||number countif(matches, arg1, arg2, ... argN)&lt;br /&gt;
|-&lt;br /&gt;
|countifop||Count the number of answered questions in the list which pass the criteria (arg op value)||number countifop(op, value, arg1, arg2, ... argN)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.date.php date]||Format a local date/time||string date(format &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;, timestamp=time()])&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.exp.php exp]||Calculates the exponent of e||number exp(number)&lt;br /&gt;
|-&lt;br /&gt;
|fixnum||Display numbers with comma as radix separator, if needed||string fixnum(number)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.floor.php floor]||Round fractions down||number floor(number)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.gmdate.php gmdate]||Format a GMT date/time||string gmdate(format &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;, timestamp=time()])&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.html-entity-decode.php html_entity_decode]||Convert all HTML entities to their applicable characters (always uses ENT_QUOTES and UTF-8)||string html_entity_decode(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.htmlentities.php htmlentities]||Convert all applicable characters to HTML entities (always uses ENT_QUOTES and UTF-8)||string htmlentities(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.htmlspecialchars.php expr_mgr_htmlspecialchars]||Convert special characters to HTML entities (always uses ENT_QUOTES and UTF-8)||string htmlspecialchars(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.htmlspecialchars-decode.php expr_mgr_htmlspecialchars_decode]||Convert special HTML entities back to characters (always uses ENT_QUOTES and UTF-8)||string htmlspecialchars_decode(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.idate.php idate]||Format a local time/date as integer||string idate(string &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;, timestamp=time()])&lt;br /&gt;
|-&lt;br /&gt;
|if||Excel-style if(test,result_if_true,result_if_false)||if(test,result_if_true,result_if_false)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.implode.php implode]||Join array elements with a string||string implode(glue,arg1,arg2,...,argN)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.intval.php intval]||Get the integer value of a variable||int intval(number &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;, base=10])&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.empty.php is_empty]||Determine whether a variable is considered to be empty||bool is_empty(var)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.is-float.php is_float]||Finds whether the type of a variable is float||bool is_float(var)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.is-int.php is_int]||Find whether the type of a variable is integer||bool is_int(var)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.is-nan.php is_nan]||Finds whether a value is not a number||bool is_nan(var)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.is-null.php is_null]||Finds whether a variable is NULL||bool is_null(var)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.is-numeric.php is_numeric]||Finds whether a variable is a number or a numeric string||bool is_numeric(var)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.is-string.php is_string]||Find whether the type of a variable is string||bool is_string(var)&lt;br /&gt;
|-&lt;br /&gt;
|join{{NewIn|2.0|b=130129}}||Join elements as a new string||join(arg1, arg2, ... argN)&lt;br /&gt;
|-&lt;br /&gt;
|list||Return comma-separated list of non-blank values||string list(arg1, arg2, ... argN)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.log.php log]|| The logarithm of number to base, if given, or the natural logarithm. ||number log(number,base=e)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.ltrim.php ltrim]||Strip whitespace (or other characters) from the beginning of a string||string ltrim(string &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;, charlist])&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.max.php max]||Find highest value||number max(arg1, arg2, ... argN)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.min.php min]||Find lowest value||number min(arg1, arg2, ... argN)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.mktime.php mktime]||Get UNIX timestamp for a date (each of the 6 arguments are optional)||number mktime([hour [, minute [, second [, month [, day [, year ]]]]]])&lt;br /&gt;
|-&lt;br /&gt;
|modulo-function||The modulo function is &#039;&#039;&#039;not supported&#039;&#039;&#039; yet. You can use the floor() function instead||floor(x/y)==(x/y)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.nl2br.php nl2br]||Inserts HTML line breaks before all newlines in a string||string nl2br(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.number-format.php number_format]||Format a number with grouped thousands||string number_format(number)&lt;br /&gt;
|-&lt;br /&gt;
|pi||Get value of pi||number pi()&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.pow.php pow]||Exponential expression||number pow(base, exp)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.quoted-printable-decode.php quoted_printable_decode]||Convert a quoted-printable string to an 8 bit string||string quoted_printable_decode(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.quoted-printable-encode.php quoted_printable_encode]||Convert a 8 bit string to a quoted-printable string||string quoted_printable_encode(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.quotemeta.php quotemeta]||Quote meta characters||string quotemeta(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.rand.php rand]||Generate a random integer, see [[Expression Manager Sample Surveys#Randomly Ask One Question Per Group|this example]]||int rand() OR int rand(min, max)&lt;br /&gt;
|-&lt;br /&gt;
|regexMatch||compare a string to a [[Using regular expressions|regular expression]]||bool regexMatch(pattern,input)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.round.php round]||Rounds a number to an optional precision||number round(val &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;, precision])&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.rtrim.php rtrim]||Strip whitespace (or other characters) from the end of a string||string rtrim(string &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;, charlist])&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.sin.php sin]||Sine||number sin(arg)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.sprintf.php sprintf]||Return a formatted string||string sprintf(format, arg1, arg2, ... argN)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.sqrt.php sqrt]||Square root||number sqrt(arg)&lt;br /&gt;
|-&lt;br /&gt;
|stddev||Calculate the Sample Standard Deviation for the list of numbers||number stddev(arg1, arg2, ... argN)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.str-pad.php str_pad]||Pad a string to a certain length with another string||string str_pad(input, pad_length &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;, pad_string])&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.str-repeat.php str_repeat]||Repeat a string||string str_repeat(input, multiplier)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.str-replace.php str_replace]||Replace all occurrences of the search string with the replacement string||string str_replace(search, replace, subject)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.strcasecmp.php strcasecmp]||Binary safe case-insensitive string comparison||int strcasecmp(str1, str2)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.strcmp.php strcmp]||Binary safe string comparison||int strcmp(str1, str2)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.strip-tags.php strip_tags]||Strip HTML and PHP tags from a string||string strip_tags(str, allowable_tags)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.stripos.php stripos]||Find position of first occurrence of a case-insensitive unicode string (starting by 0, return false if not found)|||int stripos(haystack, needle &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;, offset=0])&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.stripslashes.php stripslashes]||Un-quotes a quoted string||string stripslashes(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.stristr.php stristr]||Case-insensitive strstr||string stristr(haystack, needle &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;, before_needle=false])&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.strlen.php strlen]||Get string length||int strlen(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.strpos.php strpos]||Find position of first occurrence of an unicode string (starting by 0, return false if not found)||int strpos(haystack, needle &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt; offset=0])&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.strrev.php strrev]||Reverse a string||string strrev(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.strstr.php strstr]||Find first occurrence of a string||string strstr(haystack, needle&amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;, before_needle=false])&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.strtolower.php strtolower]||Make a string lowercase||string strtolower(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.strtotime.php strtotime]||Parse about any English textual datetime description into a Unix timestamp||int strtotime(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.strtoupper.php strtoupper]||Make a string uppercase||string strtoupper(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.substr.php substr]||Return part of an unicode string||string substr(string, start &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;, length])&lt;br /&gt;
|-&lt;br /&gt;
|sum||Calculate the sum of values in an array||number sum(arg1, arg2, ... argN)&lt;br /&gt;
|-&lt;br /&gt;
|sumifop||Sum the values of answered questions in the list which pass the criteria (arg op value)||number sumifop(op, value, arg1, arg2, ... argN)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.tan.php tan]||Tangent||number tan(arg)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.time.php time]||Return current UNIX timestamp||number time()&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.trim.php trim]||Strip whitespace (or other characters) from the beginning and end of a string||string trim(string &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;, charlist])&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.ucwords.php ucwords]||Uppercase the first character of each word in a string||string ucwords(string)&lt;br /&gt;
|-&lt;br /&gt;
|unique||Returns true if all non-empty responses are unique||boolean unique(arg1, ..., argN)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Functions that are Planned or Being Considered=== &amp;lt;!--T:176--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:177--&amp;gt;&lt;br /&gt;
Other functions that are planned (or being considered) but which are not implemented yet include the following.  Some of these are for backwards compatability with another survey tool.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:178--&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Syntax!!Meaning!!Comments&lt;br /&gt;
|-&lt;br /&gt;
|e()||returns the value of e||&lt;br /&gt;
|-&lt;br /&gt;
|formatDate(X,PAT)||return the string value of date X formatted according to Java data format pattern PAT||&lt;br /&gt;
|-&lt;br /&gt;
|formatNumber(X,PAT)||return the string value of number X formatted according to Java number format pattern PAT||&lt;br /&gt;
|-&lt;br /&gt;
|getAnsOption(X)||returns the text corresponding to the selected option for answer X||this is the same as X.shown&lt;br /&gt;
|-&lt;br /&gt;
|getAnsOption(X,Y)||returns the text corresponding to the option at index Y of node X||&lt;br /&gt;
|-&lt;br /&gt;
|getRelevance(X)||returns the relevance equation for question X||&lt;br /&gt;
|-&lt;br /&gt;
|getStartTime()||returns the date corresponding to the system time when the interview was started||&lt;br /&gt;
|-&lt;br /&gt;
|getType(X)||returns the string name of the datatype - e.g. *NA* if isNA()||&lt;br /&gt;
|-&lt;br /&gt;
|gotoFirst()||jumps to the first relevant set of questions - this violates the normal flow of the system||&lt;br /&gt;
|-&lt;br /&gt;
|gotoNext()||jumps to the next set of relevant questions - this violates the normal flow of the system||&lt;br /&gt;
|-&lt;br /&gt;
|gotoPrevious()||jumps to the previous set of relevant questions - this violates the normal flow of the system||&lt;br /&gt;
|-&lt;br /&gt;
|isAsked(X)||returns true if the answer is neither *NA*, *INVALID*, nor *UNASKED*||&lt;br /&gt;
|-&lt;br /&gt;
|isInvalid(X)||returns true if the answer is of type *INVALID*||&lt;br /&gt;
|-&lt;br /&gt;
|isNA(X)||returns true if the answer is of type *NA*||&lt;br /&gt;
|-&lt;br /&gt;
|isNotUnderstood(X)||returns true if the answer if of type *HUH*||&lt;br /&gt;
|-&lt;br /&gt;
|isRefused(X)||returns true if the answer is of type *REFUSED*||&lt;br /&gt;
|-&lt;br /&gt;
|isSpecial(X)||returns true if the answer is of type *UNASKED*, *NA*, *REFUSED*, *INVALID*, *UNKNOWN*, or *HUH*||&lt;br /&gt;
|-&lt;br /&gt;
|isUnknown(X)||returns true if the answer is of type *UNKNOWN*||&lt;br /&gt;
|-&lt;br /&gt;
|jumpTo(X)||jump to the group containing the named question -- this violates the normal flow of the system||&lt;br /&gt;
|-&lt;br /&gt;
|jumpToFirstUnasked()||jump to the first unasked question &amp;lt;strike&amp;gt; thus bypassing previous answered questions &amp;lt;/strike&amp;gt; this violates the normal flow of the system||&lt;br /&gt;
|-&lt;br /&gt;
|lastIndexOf(X,Y)||returns the last index (base 0) of string Y in string X. Returns -1 if Y is not contained within X||&lt;br /&gt;
|-&lt;br /&gt;
|list(X,...)||a string containing a comma separated list of the positive values with &amp;quot;and&amp;quot; separating the last two||&lt;br /&gt;
|-&lt;br /&gt;
|mean(X,...)||returns the mean of a list of values||&lt;br /&gt;
|-&lt;br /&gt;
|numAnsOptions(X)||returns the number of answer options that question X has||&lt;br /&gt;
|-&lt;br /&gt;
|orlist(X,...)||a string containing a comma separated list of the positive values, with &amp;quot;or&amp;quot; separting the last two||&lt;br /&gt;
|-&lt;br /&gt;
|parseDate(X,PAT)||returns the date value of string X parsed with Java date format pattern PAT||&lt;br /&gt;
|-&lt;br /&gt;
|parseNumber(X,PAT)||returns the numerical value of string X parsed with Java number format pattern PAT||&lt;br /&gt;
|-&lt;br /&gt;
|showAllResponsesExcept( questionList,attributeList,attributeTitleList)||questionList = pipe-delimited list of question identifiers; attributeList = pipe-delimited list of attributes (like question#, title, text, type - so you can decide what to show); attributeTitleList = pipe-delimited list of table headers, so can internationalize the report.||&lt;br /&gt;
|-&lt;br /&gt;
|showTheseResponses( questionList,attributeList,attributeTitleList)||questionList = pipe-delimited list of question identifiers; attributeList = pipe-delimited list of attributes (like question#, title, text, type - so you can decide what to show); attributeTitleList = pipe-delimited list of table headers, so can internationalize the report.|| &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Expression Manager Knows Which Variables are Local== &amp;lt;!--T:179--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:180--&amp;gt;&lt;br /&gt;
In order to properly build the JavaScript for page, Expression Manager needs to know which variables are set on the page, and what their JavaScript ID is (e.g. for document.getElementById(x)).  It also must know which variables are set on other pages (so that it can ensure that the needed &amp;lt;input type=&#039;hidden&#039; value=&#039;x&#039;&amp;gt; fields are present and populated).&lt;br /&gt;
&lt;br /&gt;
==Cascading Conditions== &amp;lt;!--T:181--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:182--&amp;gt;&lt;br /&gt;
If any of the variables are irrelevant, the whole equation will be irrelevant (false).  For example, in the following table, N/A means that one of the variables was not relevant&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:183--&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Operator!!Example!!a!!b!!Result&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;+ (unary)&amp;lt;/nowiki&amp;gt;||&amp;lt;nowiki&amp;gt;+a&amp;lt;/nowiki&amp;gt;||N/A|| ||false&lt;br /&gt;
|-&lt;br /&gt;
|- (unary)||-a||N/A|| ||false&lt;br /&gt;
|-&lt;br /&gt;
|!||!a||N/A|| ||false&lt;br /&gt;
|-&lt;br /&gt;
|== (or eq)||a == b||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|== (or eq)||a == b||N/A||0||false&lt;br /&gt;
|-&lt;br /&gt;
|== (or eq)||a == b||N/A||N/A||false&lt;br /&gt;
|-&lt;br /&gt;
|!= (or ne)||a != b||N/A||5|| false&lt;br /&gt;
|-&lt;br /&gt;
|!= (or ne)||a != b||N/A||N/A|| false&lt;br /&gt;
|-&lt;br /&gt;
|!= (or ne)||a != b||N/A||0||false&lt;br /&gt;
|-&lt;br /&gt;
|&amp;gt; (or gt)||a &amp;gt; b||N/A||5|| false&lt;br /&gt;
|-&lt;br /&gt;
|&amp;gt;= (or ge)||a &amp;gt;= b||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt; (or lt)||a &amp;lt; b||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;= (or le)||a &amp;lt;= b||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|and||a and b||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|and||a and b||N/A||N/A||false&lt;br /&gt;
|-&lt;br /&gt;
|or||a or b||N/A||N/A||false&lt;br /&gt;
|-&lt;br /&gt;
|or||a or b||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;+&amp;lt;/nowiki&amp;gt;||a + b||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|-||a - b||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|*||a * b||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|/||a / b||5||N/A||false&lt;br /&gt;
|-&lt;br /&gt;
|()||(a)||N/A|| ||false&lt;br /&gt;
|-&lt;br /&gt;
|(exp)||(a &amp;amp;&amp;amp; b)||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|(exp) op (exp)||(b + b) &amp;gt; (a &amp;amp;&amp;amp; b)||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|function||sum(a,b,b)||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|function||max(a,b)||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|function||min(a,b)||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|function||implode(&#039;, &#039;,a,b,a,b)||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|function||if(a,a,b)||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|function||is_empty(a)||N/A|| ||false&lt;br /&gt;
|-&lt;br /&gt;
|function||is_empty(a)||0 (or blank)|| ||true&lt;br /&gt;
|-&lt;br /&gt;
|function||!is_empty(a)||N/A|| ||false&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Overriding Cascading Conditions=== &amp;lt;!--T:184--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:185--&amp;gt;&lt;br /&gt;
Say you want to show a running total of all relevant answers.  You might try to use the equation {sum(q1,q2,q3,...,qN)}.  However, this gets translated internally to LEMif(LEManyNA(&#039;q1&#039;,&#039;q2&#039;,&#039;q3&#039;,...,&#039;qN&#039;),&#039;&#039;,sum(LEMval(&#039;q1&#039;),LEMval(&#039;q2&#039;),LEMval(&#039;q3&#039;),...,LEMval(&#039;qN&#039;))).  So, if any of the values q1-qN are irrelevant, the equation will always return false.  In this case, the sum() will show 0 until all questions are answered.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:186--&amp;gt;&lt;br /&gt;
To get around this, each variable can have a &amp;quot;.NAOK&amp;quot; suffix (meaning that Not Applicable is OK) added to it.  In such cases, the following behavior occurs.  Say you have a variable q1.NAOK&lt;br /&gt;
#q1 is not added to the LEManyNA() clause&lt;br /&gt;
#LEMval(&#039;q1&#039;) will  continue to check whether the response is relevant, and will return &amp;lt;nowiki&amp;gt;&#039;&#039;&amp;lt;/nowiki&amp;gt; if it is not (so individual irrelevant responses will be ignored, but they will not void the entire expression).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:187--&amp;gt;&lt;br /&gt;
So, the solution to the running total problem is to use the equation sum(q1.NAOK,q2.NAOK,q3.NAOK,...,qN.NAOK).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:188--&amp;gt;&lt;br /&gt;
The use of the .NAOK suffix also lets authors design surveys that have several possible paths but then converge on common paths later.  For example, say subjects answer a survey in a way that is outside the normal range of responses.  The author could alert the subjects that they may not get valid results, and ask them whether they really want to  continue with the survey.  If they say Yes, then the rest of the questions will be shown.  The condition for the &amp;quot;rest of the questions&amp;quot; would check whether the initial responses were answered within the normal range OR whether the subject said Yes to the question that is only relevant if they answered outside the normal range.&lt;br /&gt;
&lt;br /&gt;
==How does Expression Manager Support Conditional Micro-Tailoring?== &amp;lt;!--T:189--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:190--&amp;gt;&lt;br /&gt;
Here is an example of micro-tailoring (where Question Type==&#039;expr&#039; means an Equation):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:191--&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Question Code!!Relevance!!Question Type!!Question&lt;br /&gt;
|-&lt;br /&gt;
|name||1||text||What is your name?&lt;br /&gt;
|-&lt;br /&gt;
|age||1||text||How old are you?&lt;br /&gt;
|-&lt;br /&gt;
|badage||!is_empty(age)||expr||{(age&amp;lt;16) or (age&amp;gt;80)}&lt;br /&gt;
|-&lt;br /&gt;
|agestop||badage||message||Sorry, {name}, you are too {if( (age&amp;lt;16),&#039;young&#039;,if( (age&amp;gt;80),&#039;old&#039;,&#039;middle-aged&#039;) ) } for this test.&lt;br /&gt;
|-&lt;br /&gt;
|kids||!badage||yesno||Do you have children?&lt;br /&gt;
|-&lt;br /&gt;
|parents||1||expr||{!badage &amp;amp;&amp;amp; kids==&#039;Y&#039;}&lt;br /&gt;
|-&lt;br /&gt;
|numKids||parents||text||How many children do you have?&lt;br /&gt;
|-&lt;br /&gt;
|kid1||parents &amp;amp;&amp;amp; numKids &amp;gt;= 1||text||How old is your first child?&lt;br /&gt;
|-&lt;br /&gt;
|kid2||parents &amp;amp;&amp;amp; numKids &amp;gt;= 2||text||How old is your second child?&lt;br /&gt;
|-&lt;br /&gt;
|kid3||parents &amp;amp;&amp;amp; numKids &amp;gt;= 3||text||How old is your third child?&lt;br /&gt;
|-&lt;br /&gt;
|kid4||parents &amp;amp;&amp;amp; numKids &amp;gt;= 4||text||How old is your fourth child?&lt;br /&gt;
|-&lt;br /&gt;
|kid5||parents &amp;amp;&amp;amp; numKids &amp;gt;= 5||text||How old is your fifth child?&lt;br /&gt;
|-&lt;br /&gt;
|sumage||1||expr||{sum(kid1.NAOK,kid2.NAOK,kid3.NAOK,kid4.NAOK,kid5.NAOK)}&lt;br /&gt;
|-&lt;br /&gt;
|report||parents||yesno||{name}, you said you are {age} and that you have {numKids}.  The sum of ages of your first {min(numKids,5)} kids is {sumage}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:192--&amp;gt;&lt;br /&gt;
All of these questions can be on a single page (e.g. in the same group), and only the relevant questions will display.  Moreover, as you enter the ages of children, the sum() expression in the last question will dynamically update on the page.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:193--&amp;gt;&lt;br /&gt;
Expression Manager provides this functionality by surrounding each expression with a named &amp;lt;span&amp;gt; element.  Every time a value changes, it recomputes the expression that should appear in that &amp;lt;span&amp;gt; element and regenerates the display.  You can have dozens, or even hundreds, of such tailored expressions on the same page, and the page will re-display all of them in a single screen refresh.&lt;br /&gt;
&lt;br /&gt;
==Mapping of LimeSurvey 1.91+ to Expression Manager Functionality== &amp;lt;!--T:194--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:195--&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Old Feature!!New Feature!!Comments&lt;br /&gt;
|-&lt;br /&gt;
|Conditions||Relevance||You can use very complex conditional equations, and access a broader range of variables&lt;br /&gt;
|-&lt;br /&gt;
|Assessments||Equation||Any assessment scores can be re-structured into an Equation. This both ensures that the score is written to the database, and also lets you see dynamic changes to the score value on the current page&lt;br /&gt;
|-&lt;br /&gt;
|Replacements||Expression Manager||The core engine takes the input string and treats everything within curly braces as an Expression - so it handles all historical replacements types.  To avoid messing up embedded JavaScript, Expression Manager only processes content between curly braces as long as (a)  there is no leading or trailing whitespace within the curly braces - e.g. {expr} is an expression, but { expr}, {expr }, and { expr } are not expressions.  Furthermore, Expression Manager does not process content within its own strings (e.g. {list(&#039;hi&#039;,&#039;there {braces}&#039;)} generates &amp;quot;hi there {braces}&amp;quot;).  It also ignores escaped curly braces (e.g. \{this is not an expression\})&lt;br /&gt;
|-&lt;br /&gt;
|Validation||Expression Manager||The plan is to take the current min/max Question Attributes and have Expression Manager process them.  That way the min/max values can be expressions themselves&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Syntax Highlighting= &amp;lt;!--T:196--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:197--&amp;gt;&lt;br /&gt;
To help with entering and validating expressions, EM provides syntax highlighting with the following features:&lt;br /&gt;
&lt;br /&gt;
==Types and Meanings of Syntax Highlighting== &amp;lt;!--T:198--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:199--&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Color!!Sample!!Meaning!!Tooltip!!Comments&lt;br /&gt;
|-&lt;br /&gt;
|tan background||style=&#039;background-color: #eee8aa&#039;|Sample||the whole equation||none||Anything within curly braces that is recognized as an equation (e.g. there is no leading or trailing whitepace) will be color-coded with a tan background to help distinguish it from surrounding text&lt;br /&gt;
|-&lt;br /&gt;
|bold red text||style=&#039;color:#ff0000; background-color:#eee8aa&#039;|&#039;&#039;&#039;Sample&#039;&#039;&#039;||An error||Some explanation on error||Can be an unknow variable or an error in function, .... Survey can be totally broken, this don&#039;t show to public user.&lt;br /&gt;
|-&lt;br /&gt;
|blue text||style=&#039;color:#0000ff; background-color:#eee8aa&#039;|Sample||function name||meaning and allowable syntax||function names, or things that should be functions since they are followed by an opening parenthesis, are presented in bold blue text.  Tooltips show the meaning and allowable syntax for the function.&lt;br /&gt;
|-&lt;br /&gt;
|grey text||style=&#039;color:#808080; background-color:#eee8aa&#039;|Sample||string||none||single and double-quoted strings are shown in grey text&lt;br /&gt;
|-&lt;br /&gt;
|cyan text||style=&#039;color:#4169e1; background-color:#eee8aa&#039;|Sample||variable set on the same page,||&amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;name or SGQA code]: question; value; answerList showing codes for each value||Any variable that is set on the same page to the current question is shown in cyan text, showning it can be updated in javascript.  The tooltip shows its name (if you used INSERTANS:xxx) or SGQA code (if you used the new naming system), the actual question, and its current value (or blank if not set).  If the question type expects responses from an enumerated value set, the mapping of the codes to display values is show.&lt;br /&gt;
|-&lt;br /&gt;
|green text||style=&#039;color:#008000; background-color:#eee8aa&#039;|Sample||variable set on a prior page||&amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;name or SGQA code]: question; value; answerList showing codes for each value||Any variable that is set on a prior page is shown in bold green text.  The tooltip shows its name (if you used INSERTANS:xxx) or SGQA code (if you used the new naming system), the actual question, and its current value (or blank if not set).  If the question type expects responses from an enumerated value set, the mapping of the codes to display values is show.&lt;br /&gt;
|-&lt;br /&gt;
|bold pink text||style=&#039;color:#9370db; background-color:#eee8aa&#039;|Sample||variable set on a later page &amp;lt;sup&amp;gt;in general : empty at survey start, but can be filled with index or move previous&amp;lt;/sup&amp;gt;||&amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;name or SGQA code]: question; value; answerList showing codes for each value||Any variable that is set on a prior page is shown in bold pink text.  These are erorrs since the variable is  being used before it is declareed.  The tooltip shows its name (if you used INSERTANS:xxx) or SGQA code (if you used the new naming system), the actual question, and its current value (or blank if not set).  If the question type expects responses from an enumerated value set, the mapping of the codes to display values is show.&lt;br /&gt;
|-&lt;br /&gt;
|bold tan text||style=&#039;color:#a0522d; background-color:#eee8aa&#039;|Sample||a lime replacement value||the value||Lime Replacement Strings (like {TOKEN:xxx}, {PRIVACY_MESSAGE}) are shown in bold tan text.  &lt;br /&gt;
|-&lt;br /&gt;
|red text||style=&#039;color:#ff4500; background-color:#eee8aa&#039;|Sample||assignment operator (=) ||warning message||If you use one of the assignment operator (=) that operator will be displayed in red text.  This is meant to help prevent accidental re-assignment of values when you really meant to check whether a == b instead of  setting the value of a = b.&lt;br /&gt;
|-&lt;br /&gt;
|normal black text||style=&#039;color:black; background-color:#eee8aa&#039;|Sample||punctuation||none||All other punctuation within the expression is shown as normal black text.&lt;br /&gt;
|-&lt;br /&gt;
|red-boxed text||a bold red line surrounds the error||syntax error||description of the error||Any detected syntax errors are shown by surrounding the error with a red box.  The tooltip shows the error.  Examples include unmatched parentheses, use of undefined functions, passing the wrong number of arguments to functions, poorly structured expressions (e.g. missing operators between variables), trying to assign a new value to a read-only variable, trying to assign values to non-variables, or using unsupported syntax.  Note that the syntax error dectection system may only report one error in an expression even if there are multiple errors; however, if any errors are detected, at least one error will be shown.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Additional Reading= &amp;lt;!--T:202--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==[[Expression Manager Sample Surveys|Expression Manager Sample Surveys]]== &amp;lt;!--T:203--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==[[Expression Manager HowTos|Use Cases and HowTos]]== &amp;lt;!--T:204--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==[[Expression Manager Examples|Step-by-Step Examples]].== &amp;lt;!--T:205--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==[[Expression Manager for developers|Reference for Developers]]== &amp;lt;!--T:206--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==[[Expression Manager Roadmap|RoadMap/Status/ToDo List]]== &amp;lt;!--T:207--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/translate&amp;gt;&lt;/div&gt;</summary>
		<author><name>LimeAJ</name></author>
	</entry>
	<entry>
		<id>https://www.limesurvey.org/manual/index.php?title=Expression_Manager&amp;diff=73691</id>
		<title>Expression Manager</title>
		<link rel="alternate" type="text/html" href="https://www.limesurvey.org/manual/index.php?title=Expression_Manager&amp;diff=73691"/>
		<updated>2017-06-07T13:38:35Z</updated>

		<summary type="html">&lt;p&gt;LimeAJ: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;languages /&amp;gt; &amp;lt;translate&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:1--&amp;gt;&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:2--&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;simplebox&amp;quot;&amp;gt; Note: This feature is only available in LimeSurvey 1.92 or later. &amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Quick Start Tutorial= &amp;lt;!--T:3--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Overview== &amp;lt;!--T:4--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:5--&amp;gt;&lt;br /&gt;
When customizing your surveys, you typically need a way to specify the following:&lt;br /&gt;
#&#039;&#039;&#039;Navigation/Branching&#039;&#039;&#039; - letting a subject&#039;s answers change the order in which questions are asked&lt;br /&gt;
#&#039;&#039;&#039;Tailoring/Piping&#039;&#039;&#039; - how to phrase the question (such as referring to prior answers, or conjugating sentences based upon the number or gender of your subjects), or how to generate custom reports (like assessment scores or tailored advice).&lt;br /&gt;
#&#039;&#039;&#039;Validation&#039;&#039;&#039; - ensuring that answers pass certain criteria, like min and max values, or matching an input pattern&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:6--&amp;gt;&lt;br /&gt;
Expression Manager (EM) provides an intuitive way to specifying the logic for each of those features.  Nearly anything that you can write as a standard mathematical equation is a valid expression, even if you are calling functions.  EM currently provides access to 70 functions, and can be easily extended to support more.  It also lets you access your variables using human-readable variable names (rather than SGQA names).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:7--&amp;gt;&lt;br /&gt;
The following sections show the main places where Expression Manager is used&lt;br /&gt;
&lt;br /&gt;
==Relevance (Controlling Navigation/Branching)== &amp;lt;!--T:8--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:9--&amp;gt;&lt;br /&gt;
Some surveys use &amp;quot;Goto Logic&amp;quot;, such that if you answer Question 1 with option C, then jump to Question 5. This approach is very limiting, since is hard to validate, and easily breaks if you have to re-order questions.  EM uses a Boolean relevance equation to specify all of the conditions under which a question might be valid.  If the question is relevant, then the question is asked, otherwise it is Not Applicable, and the value NULL is stored in the database.  This is similar to what can be done via the Conditions editor, but EM lets you easily specify much more complex and powerful criteria (and lets you use the variable name rather than SGQA naming).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:10--&amp;gt;&lt;br /&gt;
This image shows one way to review the relevance logic for a survey.  It computes Body Mass Index.  The relevance equation is shown in square bracket right after the variable name (which is in green).  So, the relevance of weight, weight_units, height and height_units are all 1, meaning that those questions are always asked.  However, the relevance for BMI is {!is_empty(height) and !is_empty(weight)}, which means that BMI will only be computed if the subject enters a value for both height and weight (thereby avoiding the risk of a divide by zero error).  Also, the Report question is only shown if the subject answers all four main questions (height, height_units, weight, weight_units).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:11--&amp;gt;&lt;br /&gt;
[[File:tutorial1.jpg]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:12--&amp;gt;&lt;br /&gt;
Relevance is shown and editable in the following places:&lt;br /&gt;
&lt;br /&gt;
===Viewing / Editing Question-Level Relevance=== &amp;lt;!--T:13--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:14--&amp;gt;&lt;br /&gt;
This equation computes the Body Mass Index (BMI).  It is only asked if the person first enters their height and weight.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:15--&amp;gt;&lt;br /&gt;
[[File:tutorial2.jpg]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:16--&amp;gt;&lt;br /&gt;
This is the edit screen for the BMI question.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:17--&amp;gt;&lt;br /&gt;
[[File:tutorial3.jpg]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:18--&amp;gt;&lt;br /&gt;
Note that you do not use the curly braces when you enter a Relevance Equation.&lt;br /&gt;
&lt;br /&gt;
===Viewing / Editing Group-Level Relevance=== &amp;lt;!--T:19--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:20--&amp;gt;&lt;br /&gt;
This is a sample census survey.  The first page asks how many people live with you and stores that in the &amp;quot;cohabs&amp;quot; variable.  This page is only shown if you have more than one cohabitant (so it is shown for the second person cohabitating with you), and also only shows if you specified how Person One is related to you (p1_rel).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:21--&amp;gt;&lt;br /&gt;
[[File:tutorial4.jpg]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:22--&amp;gt;&lt;br /&gt;
As you can see, the group also has question-level relevance criteria, such that each question only appears once you have answered the question before it (e.g. {!is_empty(p1_sex)}).  EM combines the Group and Question-level relevance for you.  Questions in a group are only asked  if the group as a whole is relevant.  Then, only the subset of questions within the group that are relevant are asked.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:23--&amp;gt;&lt;br /&gt;
Here is the screen for editing the group-level relevance for that question:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:24--&amp;gt;&lt;br /&gt;
[[File:tutorial5.jpg]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:25--&amp;gt;&lt;br /&gt;
Note that you do not use the curly braces when you enter a Relevance Equation.&lt;br /&gt;
&lt;br /&gt;
==Tailoring/Piping== &amp;lt;!--T:26--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:27--&amp;gt;&lt;br /&gt;
EM lets you easily do simple and complex conditional tailoring of your questions.  Sometimes you just need simple substitution, like saying, &amp;quot;You said you purchased &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;Product].  What did you like best about it?&amp;quot;.  Sometimes you need conditional substitution like &amp;quot;&amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;Mr./Mrs.] &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;LastName], would you be willing to complete our survey?&amp;quot;.  In this case,  you want to use Mr. or Mrs. based upon the person&#039;s gender.  Other times you need even more complex substitution (such as based upon a mathematical computation).  EM supports each of these types of tailoring/piping.&lt;br /&gt;
&lt;br /&gt;
===Conditional Equations=== &amp;lt;!--T:28--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:29--&amp;gt;&lt;br /&gt;
The Body Mass Index example shows the ability to compute a person&#039;s BMI, even while letting them enter their height in weight in metric or non-metric units.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:30--&amp;gt;&lt;br /&gt;
[[File:tailoring7.jpg]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:31--&amp;gt;&lt;br /&gt;
Here weight_kg is {if(weight_units == &#039;kg&#039;, weight, weight * .453592)}.  This if() function means that if the subject entered the weight using kilograms, use that value, otherwise multiple the entered value (which was in pounds) by .453592 to convert it to kilograms.  The height_m variable uses a similar approach to compute the person&#039;s height in meters, even if he entered his height in inches.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:32--&amp;gt;&lt;br /&gt;
BMI computes the weight formula as {weight_kg / (height_m * height_m)}.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:33--&amp;gt;&lt;br /&gt;
Lastly, the report conditionally tailors the message for the subject, telling him what he entered. (&amp;quot;You said you are 2 meters tall and weight 70 kg.&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:34--&amp;gt;&lt;br /&gt;
Although not well shown in the above image, weight_status uses nested if() statements to categorize the person as underweight to severely obese.  You can see its equation in the Show Logic View&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:35--&amp;gt;&lt;br /&gt;
[[File:tailoring8.jpg]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:36--&amp;gt;&lt;br /&gt;
From the edit window for this question, you can see two things:&lt;br /&gt;
#Tailoring must surround expressions with Curly Braces&lt;br /&gt;
#Expressions can span multiple lines if, as in this case, you want to make it easier to read the nested conditional logic.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:37--&amp;gt;&lt;br /&gt;
[[File:tailoring9.jpg]]&lt;br /&gt;
&lt;br /&gt;
===Tailored Questions, Answers, and Reports=== &amp;lt;!--T:38--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:39--&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;simplebox&amp;quot;&amp;gt;Note: Dynamic tailoring may not work if answer options are made available in select boxes on the same question page. This results from the fact that tailoring inserts a &amp;lt;nowiki&amp;gt;&amp;lt;span&amp;gt;&amp;lt;/nowiki&amp;gt; tag which is not valid inside select options.&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:40--&amp;gt;&lt;br /&gt;
This example shows the BMI report.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:41--&amp;gt;&lt;br /&gt;
[[File:tailoring10.jpg]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:42--&amp;gt;&lt;br /&gt;
Here is the edit window for the same question.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:43--&amp;gt;&lt;br /&gt;
[[File:tailoring11.jpg]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:44--&amp;gt;&lt;br /&gt;
As you can see, anything in curly braces is treated as an expression, so is syntax-highlighted (color coded) in the prior image.  If you had any typos (such as misspelled or undefined variable names or functions), EM would show an error, such as this, showing that height_unit is an undefined variable name (it is actually height_units), and rnd() is an undefined function (the proper function name is round()).  In both cases, the errors are surrounded by a red box to make it easier to spot and fix them.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:45--&amp;gt;&lt;br /&gt;
[[File:tailoring12.jpg]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:46--&amp;gt;&lt;br /&gt;
You can also see that you can quickly create complex reports, such as a table of entered values or tailored advice.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:47--&amp;gt;&lt;br /&gt;
Please remember that all tailoring must surround expressions with Curly Braces, so that LimeSurvey knows which parts of the question are free text and which should be parsed through Expression Manager.&lt;br /&gt;
&lt;br /&gt;
==Validation== &amp;lt;!--T:48--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:49--&amp;gt;&lt;br /&gt;
EM controls how most of the advanced question options work.  These control aspects like min/max numbers of answers; min/max individual values; min/max sum values; and checking that entered values match specified string patterns.  You continue to enter those advanced question options as usual.  However, now any value in one of those fields is considered an expression, so you can have min/max criteria with complex conditional relationships to other questions.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:50--&amp;gt;&lt;br /&gt;
In all of these cases, since the advanced question option is always considered an expression, you do not use curly braces when specifying it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:51--&amp;gt;&lt;br /&gt;
The [[Expression Manager Sample Surveys|Sample Surveys]] pages shows many working examples of using expressions for validations.&lt;br /&gt;
&lt;br /&gt;
=Introduction= &amp;lt;!--T:52--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:53--&amp;gt;&lt;br /&gt;
LimeSurvey uses the new Expression Manager (EM) module which will let LimeSurvey support more complex branching, assessments, validation, and tailoring.  It will replace how LimeSurvey manages Replacements, Conditions, and Assessments on the back-end.  It will also speed up processing considerably since it eliminates most run-time database reads.  EM was developed by Dr. Thomas White (TMSWhite).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:54--&amp;gt;&lt;br /&gt;
This wiki page is the definitive reference for Expression Manager syntax and functionality.&lt;br /&gt;
&lt;br /&gt;
==Key Definitions== &amp;lt;!--T:55--&amp;gt;&lt;br /&gt;
#&#039;&#039;&#039;Expression&#039;&#039;&#039;:  Anything surrounded by curly braces&lt;br /&gt;
#*As long as there is no white space immediately after the opening brace or before the closing curly brace&lt;br /&gt;
#*The contents of Expressions are evaluted by EM, so they can contain mathematical formulas, functions, and complex string and date processing.&lt;br /&gt;
#&#039;&#039;&#039;Tailoring&#039;&#039;&#039;: Sometimes called &amp;quot;piping&amp;quot;, this is the process of conditionally modifying text&lt;br /&gt;
#*You have access to all &#039;replacement fields&#039;, TOKENs, and INSERTANS values&lt;br /&gt;
#*You also have easier access to questions, answers, and their properties.&lt;br /&gt;
#&#039;&#039;&#039;Relevance&#039;&#039;&#039; Equation:  A new question attribute controlling question visiblity&lt;br /&gt;
#*If there is a relevance equation, then the question is only shown if the relevance evaluates to true.&lt;br /&gt;
#*Internally, all array_filter and array_filter_exclude commands become sub-question-level relevance&lt;br /&gt;
#&#039;&#039;&#039;Equation&#039;&#039;&#039; Question Type:  A new question type that saves calculations or reports to the database&lt;br /&gt;
#*It is like a Boilerplate question, but its contents are saved to the database even if you set &amp;quot;Always Hide this Question&amp;quot;&lt;br /&gt;
#&#039;&#039;&#039;Question Code&#039;&#039;&#039;:  This is the preferred variable name for EM&lt;br /&gt;
#*This can be a descriptive name indicating the purpose of the question, making it easier to read complex logic&lt;br /&gt;
#*Valid question codes should NOT start with a number, so when using the question code to number your questions, simply use &amp;quot;q1&amp;quot;, or &amp;quot;q1a&amp;quot; or &amp;quot;g1q2&amp;quot;.&lt;br /&gt;
#*This is what currently becomes the variable name if you export data to SPSS or R, so if you do statistical analysis, you probably already made this unique.&lt;br /&gt;
&lt;br /&gt;
==Do I have to use EM?== &amp;lt;!--T:56--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:57--&amp;gt;&lt;br /&gt;
The short answer is No (but also yes).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:58--&amp;gt;&lt;br /&gt;
EM is fully backwards-compatible with existing surveys.  So, if you are happy to use Conditions and Assessments in the style that LimeSurvey used in versions &amp;lt;= 1.91+, you can continue to do so.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:59--&amp;gt;&lt;br /&gt;
However, EM completely replaces how LimeSurvey internally deals with Conditions.  Although you can still use the Conditions Editor to create and manage conditions, LimeSurvey 1.92 will convert those to the equivalent Relevance Equations.  As part of the upgrade, LimeSurvey 1.92 will auto-convert all existing Conditions to Relevance Equations.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:60--&amp;gt;&lt;br /&gt;
This should give you the best of both worlds - you can continue using LimeSurvey as you are used to, but will see the Relevance Equation equivalent so you can gradually migrate to Relevance Equations directly whenever you see fit.&lt;br /&gt;
&lt;br /&gt;
==Can I mix use of Conditions and Relevance?== &amp;lt;!--T:61--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:62--&amp;gt;&lt;br /&gt;
Yes. You can use the Conditions editor for some questions and the Relevance editor for others.  Conditions are auto-converted to Relevance when you save the question.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:63--&amp;gt;&lt;br /&gt;
Note, we assume that if you are using the Conditions editor, that you want those Conditions to over-write any manually entered Relevance equation.  So, if you have existing Conditions and want to manually edit the Relevance, please delete the Conditions for that question first.  Specifically, copy the generated relevance equation to a text editor, use the Conditions menu to delete all of the conditions for that question (which will also delete the relevance), then edit the question and paste the generated relevance equation from the text editor back into the relevance field for that question (and save the question).  If there is enough demand for deleting conditions without deleting the generated relevance equation, we could add a bulk conversion process.&lt;br /&gt;
&lt;br /&gt;
==How should I choose between Conditions and Relevance?== &amp;lt;!--T:64--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:65--&amp;gt;&lt;br /&gt;
Here is a list of pros and cons of each style:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:66--&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Style!!Pros!!Cons&lt;br /&gt;
|-&lt;br /&gt;
|Conditions||1. Nice GUI for creating simple conditions &amp;lt;br/&amp;gt;2. GUI well documented and understood by support team||1. Only supports simple comparisons and does not AND/OR conditions well &amp;lt;br/&amp;gt;2. Cascading conditions work erratically &amp;lt;br/&amp;gt;3. Slow - database intensive, so can slow down long surveys &amp;lt;br/&amp;gt;4. Some reported problems with re-loading conditions &amp;lt;br/&amp;gt;5. GUI doesn&#039;t scale well when there are dozens, hundreds, or thousands of questions &amp;lt;br/&amp;gt;6. May be slow to convert paper-based surveys since must use SGQA names &amp;lt;br/&amp;gt;7. Often need a programmer to custom-code logic needed for complex branching&lt;br /&gt;
|-&lt;br /&gt;
|Relevance||1. Supports very complex logic, including 80+ functions and math/string operators &amp;lt;br/&amp;gt;2. Perfect support for cascading logic &amp;lt;br/&amp;gt;3. Fast - no extra database calls, so supports 1000+ question surveys &amp;lt;br/&amp;gt;4. No problems with re-loading logic since does not require SGQA codes &amp;lt;br/&amp;gt;5. Syntax-highlighting scales to 1000+ question surveys &amp;lt;br/&amp;gt;6. Easy and fast to use for groups wanting to computerize existing paper-based suveys.  &amp;lt;br/&amp;gt;7. Easily supports semi-structured interviews and epidemiological surveys without needing a programmers||1. No GUI for simple conditions - use syntax-highlighting instead &amp;lt;br/&amp;gt;2. New, so support teams have not mastered EM yet.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:67--&amp;gt;&lt;br /&gt;
The bottom is that if you are happy with how LimeSurvey 1.91+ works, there is no reason to change what you do.&lt;br /&gt;
&lt;br /&gt;
==What are some other benefits of using EM?== &amp;lt;!--T:68--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:69--&amp;gt;&lt;br /&gt;
Here are some of the other reasons you might want to use EM.&lt;br /&gt;
#Calculations - you can create any calculation you can think of:&lt;br /&gt;
#*You have access to all common mathematical operators and functions&lt;br /&gt;
#*You have access to 70+ mathematical, date, and string processing functions&lt;br /&gt;
#*It is fairly easy for developers to add new functions if users need them&lt;br /&gt;
#Storing Calculations to Database&lt;br /&gt;
#*You can now compute simple and complex calculations and/or scale scores AND have them stored in the database without needing JavaScript.&lt;br /&gt;
#*You use the Equation question type to accomplish this.&lt;br /&gt;
#Assessments&lt;br /&gt;
#*You can now create assessments or scale scores from any question type, not just the subset that used to be supported&lt;br /&gt;
#*You can use Tailoring to show running or total assessment scores anywhere needed - even on the same page&lt;br /&gt;
#*You have more control over the reports generated based upon those assessment scores&lt;br /&gt;
#*You can store assessment scores in the database without needing JavaScript&lt;br /&gt;
#*You can hide assessment scores without needing JavaScript or CSS&lt;br /&gt;
#Replacement Fields&lt;br /&gt;
#*Instead of using {INSERTANS:SGQA}, you can just use the Question Code - this makes it easier to read and validate.&lt;br /&gt;
#*This also avoids the common need to edit questions to change the SGQA code to make everything work.&lt;br /&gt;
#Tailoring - you can conditionally display text based upon other values&lt;br /&gt;
#*Use the appropriate title for a subject, like (e.g. &amp;quot;Hello &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;Mr./Mrs.] Smith&amp;quot;)&lt;br /&gt;
#*Output gramatically correct sentences based when singular/plural matter:  (e.g. &amp;quot;You have 1 child&amp;quot; vs. &amp;quot;You have 2 children&amp;quot;)&lt;br /&gt;
#*Appropriately conjugate verbs and decline nouns based upon subject&#039;s gender and plurality.&lt;br /&gt;
#New Variable Attributes - you can access the following to do your tailoring:&lt;br /&gt;
#* (no suffix) -  an alias for qcode.code&lt;br /&gt;
#*.code - the selected response code for the question if it is relevant (otherwise blank), or the text value if it is not a coded question&lt;br /&gt;
#*.NAOK - same as .code, but can be part of calculations or lists even if irrelevant&lt;br /&gt;
#*.value - the assessment value for the question if it is relevant (otherwise blank), or the text value if it is not a coded question&lt;br /&gt;
#*.valueNAOK - same as .value, but can be part of calculations or lists even if irrelevant&lt;br /&gt;
#*.shown - the answer as displayed to the user (this is what {INSERTANS:xxx}  does)&lt;br /&gt;
#*.qid - the question ID&lt;br /&gt;
#*.gid - the group ID&lt;br /&gt;
#*.sgqa - the SGQA value for the question&lt;br /&gt;
#*.jsName - the correct javascript variable name for the question, regardless whether defined on this page or another&lt;br /&gt;
#*.qseq - the question sequence (starting from 0)&lt;br /&gt;
#*.gseq - the group sequence (starting from 0)&lt;br /&gt;
#*.mandatory - whether the question is mandatory (Y/N)&lt;br /&gt;
#*.question - the text of the question&lt;br /&gt;
#*.relevance - the relevance equation for the question&lt;br /&gt;
#*.grelevance - the relevance equation for the group&lt;br /&gt;
#*.relevanceStatus - whether or not the question is currently relevant (1 if true, 0 if false)&lt;br /&gt;
#*.type - the question type (the one character code)&lt;br /&gt;
#Dynamic On-Page Changes&lt;br /&gt;
#*All Relevance, Calculation, and Tailoring works dynamically on a page - so changes in values instantly update the page&lt;br /&gt;
#*So, you have questions dynamically appear/disappear based upon whether they are relevant&lt;br /&gt;
#*Questions are also dynamically tailored based upon responses on the page, so you can see running totals, tailored sentences and customized reports.&lt;br /&gt;
#New Data Entry Screen&lt;br /&gt;
#*In addition to using the current data-entry system, you can just use Survey-All-In-One.&lt;br /&gt;
#*This supports the on-page relevance and tailoring, so data entry clerks can quickly tab through and they will only have to enter the relevant responses&lt;br /&gt;
#*This can be critical if your data entry person needs to see the tailoring, which is also dynamic.&lt;br /&gt;
#Eliminates the need for most custom JavaScript&lt;br /&gt;
#*EM easily supports complicated computations, scoring, tailoring and conditional logic.&lt;br /&gt;
#*Some things will still need JavaScript (like custom layouts and conditionally hiding question sub-elements), but your JavaScript can use the EM functions so that you can access questions by their Qcode instead of SGQA, and access any of the question properties listed above.&lt;br /&gt;
&lt;br /&gt;
==What are some other helpful new features enabled by EM?== &amp;lt;!--T:70--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:71--&amp;gt;&lt;br /&gt;
Regardless of whether you continue to use the Conditions Editor or manually compose Relevance Equations, you get these additional benefits:&lt;br /&gt;
#You can create more complex validation criteria&lt;br /&gt;
#*All of the advanced question attribute (like max_answers, min_num_value_n, max_num_value) can use Expressions.  So, you min/max criteria can be easily adjusted based upon prior responses, even if they are on the same page.&lt;br /&gt;
#*EM also handles all regular-expression-based validation, so you can robustly combine preg and equation-based question attributes.&lt;br /&gt;
#Easy Re-ordering (or deleting) of Questions and Groups&lt;br /&gt;
#*Prior to version 1.92, you could not re-order questions or groups if LimeSurvey thought that such-re-ordering could break conditions in which they were used.  Similarly, you could not delete questions if any other questions depended upon them.&lt;br /&gt;
#*With EM&#039;s syntax highlighting, it is easy to see and validate whether you try to use questions before they are declared.  So, we now let you re-order or delete questions and groups whenever you like.  EM will update all of the syntax highlighting to show you potential errors.&lt;br /&gt;
#*The re-order questions view has been enhanced to help with such review.  It now shows the question&#039;s relevance equation and tailoring, so you can immediately see whether any variables become pink (meaning they are used before being declared).&lt;br /&gt;
#The Question/Group Navigation Index is always available and accurate&lt;br /&gt;
#*Prior to version 1.92, these indexes were not available if there were complex conditions&lt;br /&gt;
#*With EM, we can guarantee that they are accurate.&lt;br /&gt;
#*Subjects can even jump back, to a prior question, change the answer, then jump forward (or submit)&lt;br /&gt;
#**When jumping forwards, EM will re-validate all of the intervening questions/groups.&lt;br /&gt;
#**If any questions become irrelevant, they will be NULLed in the database so that your data is internally consistent&lt;br /&gt;
#**If any questions become relevant or newly fail mandatory or validation rules, EM will stop on that page and force the user to answer those questions before jumping to their final destination.&lt;br /&gt;
#Auto-conversion of Conditions to Relevance&lt;br /&gt;
#*When you upgrade your database, all existing surveys that have conditions will have relevance equations generated for them&lt;br /&gt;
#*Whenever you import a survey, relevance equations will be created as needed&lt;br /&gt;
#*Whenever you add, delete, or modify conditions, EM will generate the appropriate relevance equation.&lt;br /&gt;
#Convenient Syntax Highlighting&lt;br /&gt;
#*When EM shows the relevance equation, it will show the Qcode, even if you entered an SGQA code, as we assume this will be easier to read.&lt;br /&gt;
#*All variables are color coded to show whether they were declared before or after the current question (or before or after the current group).  This lets you quickly detect and fix cases where you try to use variables for relevance (including array_filter), tailoring, or validation equations prior to declaring them.&lt;br /&gt;
#*In addition, if you hover your mouse over the color-coded variable, you will see the most important metadata about that question.   This includes the Group Sequence #, Question Sequence #, Qcode, Text of the question, and all available answer choices (if it is a question type with enumerated answer choices).&lt;br /&gt;
#**The list of answer choices uses this syntax:  &#039;answers&#039;:{key:val, ... }.&lt;br /&gt;
#**&#039;&#039;key&#039;&#039; has the syntax &#039;&#039;&#039;&#039;scale~code&#039;&#039;&#039;&#039; where &#039;&#039;scale&#039;&#039; is the answer scale (e.g. for dual scale), and &#039;&#039;code&#039;&#039; is the answer code.&lt;br /&gt;
#**&#039;&#039;val&#039;&#039; has the syntax &#039;&#039;&#039;&#039;value~shown&#039;&#039;&#039;&#039; where &#039;&#039;value&#039;&#039; is the assessment value (if using assessments, otherwise &#039;&#039;code&#039;&#039;)(e.g. Qcode.value), and &#039;&#039;shown&#039;&#039; is the display value as seen by the subject (e.g. Qcode.shown)&lt;br /&gt;
#**This means that many surveys can use calculations without needing assessment mode.  If you have enumerated answer options  that are unique, non-decimal, and non-negative, you can simply do calculations on the Qcode.code values.&lt;br /&gt;
#Easy review of entire survey logic and content&lt;br /&gt;
#*There is a new Show Survey Logic feature that lets you see everything about the survey (or group or question) on a single page.&lt;br /&gt;
#*It shows the Group, Question, Sub-Question, and Answer-level details for the selected scope (survey vs. group vs. question)&lt;br /&gt;
#*It also shows the relevance, sub-question-level relevance (for array_filter and array_filter_exclude), and generated validation equation (for preg and any validation rules like min/max sum/number of values), and all non-blank question attributes.&lt;br /&gt;
#*Everything is syntax-highlighted so that you can see potential syntax errors (like unbalanced parentheses or use of variables before they were declared)&lt;br /&gt;
#*The syntax-highligting supports rapid navigation and editing of the survey.&lt;br /&gt;
#**If you click on a variable name, it opens a browser window (or tab) that shows you that question and lets you edit it.&lt;br /&gt;
#**If you click on a group name, it opens a browser window (or tab) showing the group-reorder view so that you can easily move questions around.&lt;br /&gt;
#**All of the question attributes are also syntax highlighted.  This lets you set and see expressions within advanced question options (like basing the max/min number/sum of values on an expression)&lt;br /&gt;
#*The EM author used similar view (a little cleaner) to let his collaborating Epidemiologists and Institutional Review Board validate and authorize surveys with thousands of questions in highly branched and tailored structured interviews&lt;br /&gt;
&lt;br /&gt;
==How Backwards Compatible is EM with 1.91+?== &amp;lt;!--T:72--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:73--&amp;gt;&lt;br /&gt;
LimeSurvey 1.92 is fully backwards-compatible with 1.91+ with one exception/caveat:  1.92 handles less-than / greater-than comparisons against empty values differently than 1.91+.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:74--&amp;gt;&lt;br /&gt;
One of the LimeSurvey demo surveys uses a set of conditions that translates to this relevance equation:  {(age &amp;lt; 16) or (age == 20) or ... or (age == 80)}. In LimeSurvey 1.91+, (age &amp;lt; 16) is FALSE when there is no answer (the value is blank).  However, in LimeSurey 1.92, (age &amp;lt; 16) is TRUE when there is no answer, since both PHP and JavaScript treat blank as 0 in mathematical comparisons.  Thus, 1.91+ would hide that question when age was unanswered, but 1.92 would show it.  We went to great pains to prevent this, but since we needed to have the Expressions generate identical results in PHP and JavaScript, there was no way to make 1.92 treat &amp;quot;&amp;quot; &amp;lt; 16 as FALSE.  Fortunately, there is an easy work-around for this.  If you want (age &amp;lt; 16) to be FALSE, then use this expression instead: {(!is_empty(age) and age &amp;lt; 16)}.  You can use the new [[Show Logic File|Survey Logic File]] view to quickly identify and fix any such comparisons in your survey.&lt;br /&gt;
&lt;br /&gt;
=Getting Started= &amp;lt;!--T:75--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:76--&amp;gt;&lt;br /&gt;
The best way to get started with EM is to:&lt;br /&gt;
*Install the latest stable version from http://www.limesurvey.org/en/download &lt;br /&gt;
*Import and explore the [[Expression Manager Sample Surveys|sample surveys]].&lt;br /&gt;
*Explore the [[Expression Manager HowTos|use cases and HowTos]] and [[Expression Manager Examples|step-by-step examples]].&lt;br /&gt;
*Explore the EM documentation (this page)&lt;br /&gt;
*Examine the built-in EM test suite&lt;br /&gt;
**From any survey, under tools, select the EM option&lt;br /&gt;
**Available Functions lists the 70+ functions and syntax&lt;br /&gt;
**Unit Tests of Isolated Expressions&lt;br /&gt;
***shows examples of using all EM functions and operators, and the PHP and JavaScript results&lt;br /&gt;
***note there are few functions that generate different results in the PHP and JavaScript versions, so this page lets you plan your EM logic accordingly.&lt;br /&gt;
&lt;br /&gt;
=What Functionality does Expression Manager Extend/Replace? (LimeSurvey &amp;lt;= 1.91+)= &amp;lt;!--T:77--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Conditions =&amp;gt; Relevance== &amp;lt;!--T:78--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:79--&amp;gt;&lt;br /&gt;
Conditions controlled which  questions are visible.  The general syntax was &#039;&#039;SGQA operator Value&#039;&#039;, like &#039;&#039;111X2X3 == &amp;quot;Y&amp;quot;&#039;&#039;.  Conditions could be ANDed or ORed together, but mixing ANDs and ORs was difficult.  The conditions themselves were stored in a separate table, and large portion of LimeSurvey&#039;s code was devoted to managing Conditions.  Because of extensive database access, processing large numbers of conditions could cause noticable performance problems.  Furthermore, once you had conditions assigned to questions or groups, you were often not allowed to re-order or delete them.&lt;br /&gt;
&lt;br /&gt;
==Assessments =&amp;gt; Equations and  Micro-Tailoring== &amp;lt;!--T:80--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:81--&amp;gt;&lt;br /&gt;
Assessments let users create scale scores from a collection of questions.  However, they could not dynamically change on the current page, and their values were not stored to the database.&lt;br /&gt;
&lt;br /&gt;
==Replacements =&amp;gt; Micro-Tailoring== &amp;lt;!--T:82--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:83--&amp;gt;&lt;br /&gt;
Users could tailor some messages and questions based  upon prior responses.  For example, a question might be, &#039;&#039;{TOKEN:FIRSTNAME}, you said {INSERTANS:111X3X4} was your favorite sport&#039;&#039;.  However, it was not possible to do conditional tailoring (like say &amp;quot;Mr.&amp;quot; or &amp;quot;Mrs.&amp;quot; depending upon the person&#039;s gender), or conjugate verbs or decline nouns without fancy JavaScript.  Authors could implement surveys that seemed to tailor questions, but it required separate questions for each permutation, and complex conditions to decide which questions to display.&lt;br /&gt;
&lt;br /&gt;
==Validation== &amp;lt;!--T:84--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:85--&amp;gt;&lt;br /&gt;
Question could be validated with Regular expressions, or minimum/maximum values, or let an SGQA response serve as the minimum or maximum value.  However, validations could not be based upon calculations of other variables without fancy JavaScript.&lt;br /&gt;
&lt;br /&gt;
==Equations== &amp;lt;!--T:86--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:87--&amp;gt;&lt;br /&gt;
Equations were not supported without fancy JavaScript.&lt;br /&gt;
&lt;br /&gt;
==Equation Question Type== &amp;lt;!--T:88--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:89--&amp;gt;&lt;br /&gt;
Equations could not be saved to the database (e.g. the final score for an assessment) without fancy JavaScript.&lt;br /&gt;
&lt;br /&gt;
=How Will Expression Manager Replace/Extend That Functionality?= &amp;lt;!--T:90--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:91--&amp;gt;&lt;br /&gt;
The Expression Manager is a new core module within LimeSurvey that makes it much easier to support the type of complex functionality that used to require custom JavaScript.  It is also replacing the way LimeSurvey currently manages Conditions and Assessments.&lt;br /&gt;
&lt;br /&gt;
==New Terminology When Referring to Expression Manager (EM)== &amp;lt;!--T:92--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:93--&amp;gt;&lt;br /&gt;
EM &amp;quot;thinks&amp;quot; of its functionality in the following terms:&lt;br /&gt;
*&#039;&#039;&#039;Relevance-based Branching&#039;&#039;&#039; - if a question is relevant, then ask it, otherwise don&#039;t (e.g. make it invisible, and mark it as NULL in the database).  There is a new Relevance field for all Question types, and also for each Group (so you can apply a set of conditions to an entire group without having to copy the same condition to each question, and/or combine group and question-level conditional logic).&lt;br /&gt;
*&#039;&#039;&#039;Tailoring&#039;&#039;&#039; - Once you know which questions should be asked, tailoring (sometimes called &#039;&#039;piping&#039;&#039;) specifies how the question should be asked. This lets you support not only simple subsitution (like {TOKEN:FIRSTNAME}), but also conjugation of verbs and declination of nouns based upon the gender or number of your subjects.  It also lets you change the message you deliver to a subject based upon whether they answered (or how they answered) other questions.&lt;br /&gt;
*&#039;&#039;&#039;Equations&#039;&#039;&#039; - EM adds a new question type called Equation which stores the result of an Expression.  These equations results are computed and written to the database, even if you hide them on the page.  Thus, they are useful for hidden scoring calculations, navigation based upon complex equations, assessments, and reports that should be generated and easily available within the database.&lt;br /&gt;
&lt;br /&gt;
===Relevance and Cascading Relevance=== &amp;lt;!--T:94--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:95--&amp;gt;&lt;br /&gt;
Every question type now has a Relevance option which controls whether the question is displayed.  EM processes each of the Relevance Equations in the order they should appear in the survey.  If the expression is true (or missing - to support legacy surveys), the question will be displayed. If it is not relevant, then the question will be hidden, and the value will be NULLed in the database.  If there are no relevant questions in a group, the entire group will be skipped.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:96--&amp;gt;&lt;br /&gt;
Moreover, if any of the variables within an expression is irrelevant, then the expression always evaluates to false.  This enables Cascading Relevance so that you do not have to write very long Relevance equations for each question.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:97--&amp;gt;&lt;br /&gt;
Say you have 5 questions Q1-Q5, and you only want to show Q2 if Q1 was answered, and Q3 if Q2 was answered, etc.  The relevance equations might be:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:98--&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Question Code!!Relevance!!Question&lt;br /&gt;
|-&lt;br /&gt;
|Q1||1||What is your name?&lt;br /&gt;
|-&lt;br /&gt;
|Q2||Q1||{Q1}, how old are you?&lt;br /&gt;
|-&lt;br /&gt;
|Q3||Q2||So, you are {Q2} years old.  Are you married?&lt;br /&gt;
|-&lt;br /&gt;
|Q4||Q3 == &amp;quot;Y&amp;quot;||{Q1}, how long have you been married?&lt;br /&gt;
|-&lt;br /&gt;
|Q5||Q4||How many children do you have, {Q1}?&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:99--&amp;gt;&lt;br /&gt;
The relevance calculations also work in JavaScript - so you could put all the above questions on one page and it would still work as expected.  In fact, EM totally replaces how EM processes Survey vs. Group vs. Question-at-a-time survey formats.  They now all use the exactly same navigation engine so they work identically regardless of survey style.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:100--&amp;gt;&lt;br /&gt;
As long as you are on the same page, any data you entered will still be there, just hidden.  So, if you enter some information, then choose an option that makes them irrelevant, then make them relevant again, your answers will still be available.  However, as soon as you move to a different page, all irrelevant responses will be lost to integrity of the dataset.&lt;br /&gt;
&lt;br /&gt;
===Group-Level Relevance=== &amp;lt;!--T:101--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:102--&amp;gt;&lt;br /&gt;
Expression Manager also supports group-level relevance.  This makes it easier to implement looping.   Say you want to collect information about up to 10 entities (such a products or people in a household), where you first determine how many entities need follow-up (such as by asking how many people live in a household, or having people check which products they like from a long list).  After knowning how many entities need follow-up, you can use Group-level relevance like {count &amp;gt;= 1}, {count &amp;gt;=2}, ... {count &amp;gt;= 10} for each of the 10 groups of follow-up questions.  Within each group, you can have question-level conditional logic (e.g. gender or age-specific follow-up questions for each subject).  The question and group-level relevance equations are ANDed together to determine which should be shown.&lt;br /&gt;
&lt;br /&gt;
===Tailoring / Piping=== &amp;lt;!--T:103--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:104--&amp;gt;&lt;br /&gt;
Anything within curly braces is now treated as an Expression (with one exception described below).  Expressions have acccess to all of the LimeReplacementFields, all of the variables (via several aliases), all typical equation operators (mathematical, logical, and comparison), and dozens of functions (that even work dynamically on the client-side).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:105--&amp;gt;&lt;br /&gt;
Using these equations, you can do things such as:&lt;br /&gt;
#Conditionally show tailored messages to the respondants based upon prior responses&lt;br /&gt;
#Create Assessments and show Assessment results (or conditionally branch or show messages) based upon those results, all without using the Assessments module itself&lt;br /&gt;
#Conjugate verbs and decline nouns within questions, answers, and reports.&lt;br /&gt;
#Show summaries of responses before the &amp;quot;Show your answers&amp;quot; page at the end of the survey&lt;br /&gt;
&lt;br /&gt;
===Equations=== &amp;lt;!--T:106--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:107--&amp;gt;&lt;br /&gt;
There is a new question type called  Equation.  It is like a Boilerplate questions, except that it stores the value of what is displayed in the database.  So, if the Equation Question text contains an Assessment computation, that value would be stored in the database in a variable that can be displayed within public or private statistics.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:108--&amp;gt;&lt;br /&gt;
This solves a common request for storing Assessment scores within the database&lt;br /&gt;
&lt;br /&gt;
==Syntax== &amp;lt;!--T:109--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:110--&amp;gt;&lt;br /&gt;
Anything contained within curly braces is now considered an Expression (with one exception:  there must be no leading or trailing whitespace - this is needed to ensure the Expression Manager does not try to process embedded JavaScript).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:111--&amp;gt;&lt;br /&gt;
Note, it is OK for expressions to span multiple lines, as long as there is no whitespace after the opening  curly brace or before the closing curly brace.  This is especially helpful for nested if() statements like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:112--&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;{if(is_empty(PFTotals),&lt;br /&gt;
 &#039;&#039;,&lt;br /&gt;
 if(PFTotals &amp;gt;= -5 &amp;amp;&amp;amp; PFTotals &amp;lt;= -4,&lt;br /&gt;
   &#039;Very Soft&#039;,&lt;br /&gt;
   if(PFTotals &amp;gt;= -3 &amp;amp;&amp;amp; PFTotals &amp;lt;= -2,&lt;br /&gt;
     &#039;Soft&#039;,&lt;br /&gt;
     if(PFTotals == -1,&lt;br /&gt;
       &#039;Somewhat Soft&#039;,&lt;br /&gt;
       if(PFTotals == 0,&lt;br /&gt;
         &#039;Moderate&#039;,&lt;br /&gt;
         if(PFTotals == 1,&lt;br /&gt;
           &#039;Somewhat Hard&#039;,&lt;br /&gt;
           if(PFTotals &amp;gt;= 2 &amp;amp;&amp;amp; PFTotals &amp;lt;= 3,&lt;br /&gt;
             &#039;Hard&#039;,&lt;br /&gt;
             if(PFTotals &amp;gt;= 4 &amp;amp;&amp;amp; PFTotals &amp;lt;= 5,&lt;br /&gt;
               &#039;Very Hard&#039;,&lt;br /&gt;
               &#039;&#039;&lt;br /&gt;
             )&lt;br /&gt;
           )&lt;br /&gt;
         )&lt;br /&gt;
       )&lt;br /&gt;
     )&lt;br /&gt;
   )&lt;br /&gt;
 )&lt;br /&gt;
)}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:138--&amp;gt;&lt;br /&gt;
&amp;lt;div id=&amp;quot;EMsyntax&amp;quot;&amp;gt;Expression Manager supports the following syntax:&amp;lt;/div&amp;gt;&lt;br /&gt;
*All standard mathematical operators (e.g. +,-,*,/,!)&lt;br /&gt;
*All standard comparison operators (e.g. &amp;lt;,&amp;lt;=,==,!=,&amp;gt;,&amp;gt;=, plus these equivalents:  lt,le,eq,ne,gt,ge)&lt;br /&gt;
*Parentheses (so you can group sub-expressions)&lt;br /&gt;
*Conditional operators (e.g. &amp;amp;&amp;amp;,| | and these equivalents: and,or)&lt;br /&gt;
*Single and double-quoted strings (which can each embed strings with the other quote type)&lt;br /&gt;
*Comma operator (so can have a list of expressions and just return the final result)&lt;br /&gt;
*Assignment operator (=)&lt;br /&gt;
*Pre-defined variables (to refer to questions, question attributes, and responses) - e.g. all of the SGQA codes&lt;br /&gt;
*Pre-defined functions (there are already 70+, and it is easy to add more)&lt;br /&gt;
&lt;br /&gt;
=== Operators === &amp;lt;!--T:211--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:139--&amp;gt;&lt;br /&gt;
EM syntax follows normal operator precedence:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:140--&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Level!!Operator(s)!!Description&lt;br /&gt;
|-&lt;br /&gt;
|1||()||parentheses for grouping or calling functions&lt;br /&gt;
|-&lt;br /&gt;
|2||! - +||unary operators: not, negation, unary-plus&lt;br /&gt;
|-&lt;br /&gt;
|3||* /||times, divide&lt;br /&gt;
|-&lt;br /&gt;
|4||+ -||plus, minus&lt;br /&gt;
|-&lt;br /&gt;
|5||&amp;lt; &amp;lt;= &amp;gt; &amp;gt;= lt le gt ge||relative comparisons&lt;br /&gt;
|-&lt;br /&gt;
|6||== != eq ne||equality comparisons&lt;br /&gt;
|-&lt;br /&gt;
|7||and||logical AND&lt;br /&gt;
|-&lt;br /&gt;
|8||or||logical OR&lt;br /&gt;
|-&lt;br /&gt;
|9||=||assignment operator&lt;br /&gt;
|-&lt;br /&gt;
|10||,||comma operator&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:141--&amp;gt;&lt;br /&gt;
Note, for consistency between JavaScript and PHP, the plus operator (+) does addition if both operands are numeric, but does concatenation if both parts are non-numeric strings.  However, we recommend using the join() function for concatenation, as that makes your intent more clear, and avoids unexpected results if you were expecting strings but got numbers instead (or vice versa).&lt;br /&gt;
&lt;br /&gt;
===Caution about using Assignment Operator (=)=== &amp;lt;!--T:142--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:143--&amp;gt;&lt;br /&gt;
Note, you should avoid using the assignment operators unless absolutely necessary, since they may cause unexpected side-effects.  For example, if you change the value of a previous response, the cascading relevance and validation logic between that question and the current question is not re-computed, so you could end up with internally inconsistent data (e.g. questions that stay answered but should have been NULLed, or questions that are skipped but should have been answered).  In general, if you want to assign a value to a variable, you should create an Equation question type, and use an expression to set its value.  However, there are some rare times that people really need this operator, so we made it available.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:144--&amp;gt;&lt;br /&gt;
To help caution you about this operator, it is shown in red font within the syntax equations (so that you don&#039;t confuse it with &amp;quot;==&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
===Using Assignment Operator=== &amp;lt;!--T:145--&amp;gt;&lt;br /&gt;
The main reasons you may want to use assignment are:&lt;br /&gt;
*You need to set the default value for a question that does not accept defaults via equation (such as list radio, where the user interface lets you pick one of the answer options, but does not let you enter an equation).  However, be careful, as LimeSurvey will not be able to validate that your equation generates one of the allowable answers for that question.&lt;br /&gt;
*You need to forcibly change the response to a previous question based upon a later response&lt;br /&gt;
* etc...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:212--&amp;gt;&lt;br /&gt;
You can use all expression manager system for this purpose. It&#039;s better to use an [[Question_type_-_Equation|Equation question]] type to this purpose.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:213--&amp;gt;&lt;br /&gt;
Some example:&lt;br /&gt;
* Set answer to a short text question in lowercase : &amp;lt;code&amp;gt;{QCODE=strtolower(QCODE.NAOK)}&amp;lt;/code&amp;gt;&lt;br /&gt;
* Set a default answer to an array question type at start of a survey : &amp;lt;code&amp;gt;{Q1_SQ1=(is_empty(Q1_SQ1.NAOK),&amp;quot;A99&amp;quot;,Q1_SQ1.NAOK)}&amp;lt;/code&amp;gt;&lt;br /&gt;
* Set a default answer to an array texts question type at start of a survey : &amp;lt;code&amp;gt;{Q1_SQY1_SQX1 = (is_empty(Q1_SQY1_SQX1.NAOK),&amp;quot;Inserted answer&amp;quot;, Q1_SQY1_SQX1.NAOK)}&amp;lt;/code&amp;gt;&lt;br /&gt;
* Set an answer with condition : &amp;lt;code&amp;gt;{QCODE=if(YesNo=&amp;quot;Y&amp;quot;,&amp;quot;A1&amp;quot;,&amp;quot;&amp;quot;)}&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== XSS security == &amp;lt;!--T:214--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:215--&amp;gt;&lt;br /&gt;
With XSS enable, some expression manager system can not be used : &lt;br /&gt;
* starting a HTML tag in expression but ending in another expression&lt;br /&gt;
* use a complex expression in URL. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:216--&amp;gt;&lt;br /&gt;
Example and workaround&lt;br /&gt;
* &amp;lt;code&amp;gt;{if( 1 ,&amp;quot;&amp;amp;lt;strong&amp;amp;gt;&amp;quot;,&amp;quot;&amp;quot;)}information{if( 1 ,&amp;quot;&amp;amp;lt;/strong&amp;amp;gt;&amp;quot;,&amp;quot;&amp;quot;)}&amp;lt;/code&amp;gt; is broken with XSS security, here you can use &amp;lt;code&amp;gt;{if(1,&amp;quot;&amp;lt;strong&amp;amp;gt;information&amp;amp;lt;/strong&amp;amp;gt;&amp;quot;,&amp;quot;information&amp;quot;)}&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;&amp;amp;lt;a href=&amp;quot;/script.php?value={if(QCODE == &amp;quot;Y&amp;quot;,&amp;quot;yes&amp;quot;,&amp;quot;no&amp;quot;)}&amp;quot;&amp;amp;gt;next&amp;amp;lt;/a&amp;amp;gt;&amp;lt;/code&amp;gt;, here you can use an equation question because using a complete question code is OK : &amp;lt;code&amp;gt;&amp;amp;lt;a href=&amp;quot;/script.php?value={EQUATION.NAOK}&amp;quot;&amp;amp;gt;next&amp;amp;lt;/a&amp;amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Access to Variables== &amp;lt;!--T:146--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:147--&amp;gt;&lt;br /&gt;
Expression Manager provides read-only access to whichever variables we might need.  For backwards compatibility, it provides access to the following:&lt;br /&gt;
*TOKEN:xxx - the value of a TOKEN (e.g. TOKEN:FIRSTNAME, TOKEN:ATTRIBUTE_5) (Only for NOT anonymous survey).&lt;br /&gt;
*[[Adding a question#Information_from_previous_answers|INSERTANS:SGQA]] - the display value of an answer (e.g. &amp;quot;Yes&amp;quot;). For Expression Manager it&#039;s the same that using {QCODE.shown}.&lt;br /&gt;
*All [[The_template_editor#Keywords|{XXX} values used by templates]].&lt;br /&gt;
*In question text, you can use {QID} replaced by the question id and {SGQ} replaced by the SGQA of the question&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:148--&amp;gt;&lt;br /&gt;
In addition, Expression Manager lets you refer to variables by the Question Code (the &#039;title&#039; column in the questions table within the database).  This is also the variable label used when you export your data to SPSS, R, or SAS.  For example, if you have questions about name, age, and gender, you could call those variables &#039;&#039;name&#039;&#039;, &#039;&#039;age&#039;&#039;, and &#039;&#039;gender&#039;&#039; instead of &#039;&#039;12345X13X22&#039;&#039;, &#039;&#039;12345X13X23&#039;&#039;, and  &#039;&#039;12345X13X24&#039;&#039;.  This makes equations easier for everyone to read and validate the logic, plus makes it possible to shuffle questions around without having to keep track of group or question numbers.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:210--&amp;gt;&lt;br /&gt;
&amp;lt;div class=&#039;simplebox&#039;&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Important:&#039;&#039;&#039; It is only safe to refer to variables that occur in preceding pages or questions.&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:149--&amp;gt;&lt;br /&gt;
Furthermore, Expression Manager lets you access many properties of the Question:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:150--&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Syntax!!Meaning!!Example!!Example Result&lt;br /&gt;
|-&lt;br /&gt;
|Qcode||an alias for Qcode.code||{implode(&#039;,&#039;,name,gender)}||&#039;Tom&#039;,&#039;M&#039;&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.code||the selected response code for the question if it is relevant (otherwise blank), or the text value if it is not a coded question||{implode(&#039;,&#039;,name.code,gender.code)}||&#039;Tom&#039;,&#039;M&#039;&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.NAOK||same as Qcode - see discussion of NAOK||{gender.NAOK}||&#039;M&#039;&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.value||the assessment value for the question if it is relevant (otherwise blank), or the text value if it is not a coded question||{gender.value}||&#039;1&#039;&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.valueNAOK||same as Qcode.value - see discussion about NAOK||{gender.valueNAOK}||&#039;1&#039;&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.shown||the dispay value for the question||{implode(&#039;,&#039;,name.shown,gender.shown)}||&#039;Tom&#039;,&#039;Male&#039;&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.question||the text of the question||{gender.question}||&#039;What is your gender?&#039;&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.mandatory||whether the question is mandatory (Y/N)||{gender.mandatory}||&#039;N&#039;&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.qid||the internal question number (not the sequential number)||{gender.qid}||337&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.type||the question type||{gender.type}||&#039;G&#039;&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.jsName||the correct javascript name for the question, regardless whether declared on or off this page||{gender.jsName}||&#039;java1827X3X337&#039;&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.gid||the internal group number (not the sequential number)||{gender.gid}||3&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.qseq||the sequential number of the question, starting from 0||{gender.qseq}||5&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.gseq||the sequential number of the group, starting from 0||{gender.gseq}||1&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.relevanceStatus||whether the question is currently relevant (0 or 1)||{gender.relevanceStatus}||1&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.relevance||the question-level relevance equation||{gender.relevance}||&#039;!is_empty(name)&#039;&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.grelevance||the  group-level relevance equation||{gender.grelevance}||&#039;num_children &amp;gt;= 5&#039;&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.sgqa||the SGQA value for this question||{gender.sgqa}||&#039;1827X3X337&#039;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== HTML editor issue=== &amp;lt;!--T:151--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:217--&amp;gt;&lt;br /&gt;
{{Alert|This issue is fixed after 2.05 build 140803}} &lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:152--&amp;gt;&lt;br /&gt;
If you use HTML editor, some characters are replaced by HTML entities.&lt;br /&gt;
* &amp;amp; by &amp;amp;amp;amp;&lt;br /&gt;
* &amp;lt; by &amp;amp;amp;lt;&lt;br /&gt;
* &amp;gt; by &amp;amp;amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:209--&amp;gt;&lt;br /&gt;
If you use HTML editor you need to use :&lt;br /&gt;
* and for &amp;amp;&lt;br /&gt;
* lt for &amp;lt;&lt;br /&gt;
* le for &amp;lt;=&lt;br /&gt;
* gt for &amp;gt;&lt;br /&gt;
* ge for &amp;gt;=&lt;br /&gt;
&lt;br /&gt;
==Qcode Variable Naming== &amp;lt;!--T:153--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:154--&amp;gt;&lt;br /&gt;
Here are the details of how to construct a Qcode (and access some properties) by question type.  In general, Qcodes are constructed as:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:155--&amp;gt;&lt;br /&gt;
  QuestionCode . &#039;_&#039; . SubQuestionID . &#039;_&#039; . ScaleId&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:208--&amp;gt;&lt;br /&gt;
For comment and other, question code are QuestionCode_comment and QuestionCode_other&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:156--&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Type!!Description!!Code!!SubQs!!Answer Options!!Scales!!Answer Code!!Answer Shown!!Relevance&lt;br /&gt;
|-&lt;br /&gt;
|5||5 Point Choice Radio-Buttons||Q1|| ||1-5|| ||{Q1}||{Q1.shown}||{Q1==3}&lt;br /&gt;
|-&lt;br /&gt;
|B||Array (10 Point Choice) Radio-Buttons||Q2||L1-L6||1-10|| ||{Q2_L2}||{Q2_L2.shown}||{Q2_L2==7}&lt;br /&gt;
|-&lt;br /&gt;
|A||Array (5 Point Choice) Radio-Buttons||Q3||1-5||1-5|| ||{Q3_1}||{Q3_1.shown}||{Q3_1&amp;gt;=3}&lt;br /&gt;
|-&lt;br /&gt;
|1||Array (Flexible Labels) Dual Scale||Q4||sq1-sq5||0:a1-a3||1:b1-b3||{Q4_sq1_0}||{Q4_sq1_1.shown}||{Q4_sq1_1==&#039;b2&#039;}&lt;br /&gt;
|-&lt;br /&gt;
|H||Array (Flexible) - Column Format||Q5||1-5||s,m,t|| ||{Q5_1}||{Q5_1.shown}||{Q5_1==&#039;s&#039;}&lt;br /&gt;
|-&lt;br /&gt;
|F||Array (Flexible) - Row Format||Q6||F1-F5||1-5|| ||{Q6_F3}||{Q6_F3.shown}||{Q6_F3==4}&lt;br /&gt;
|-&lt;br /&gt;
|E||Array (Increase/Same/Decrease) Radio-Buttons||Q7||1-7||I,S,D|| ||{Q7_4}||{Q7_4.shown}||{Q7_4==&#039;D&#039;}&lt;br /&gt;
|-&lt;br /&gt;
|:||Array (Multi Flexi) 1 To 10||Q8||ls1,todo,ls2||min,max,avg|| ||{Q8_ls1_max}||{Q8_ls2_avg.shown}||{Q8_ls2_min==7}&lt;br /&gt;
|-&lt;br /&gt;
|;||Array (Multi Flexi) Text||Q9||hp,st,sw||1st,2nd,3rd|| ||{Q9_hp_3rd}||{Q9_hp_3rd.shown}||{Q9_hp_3rd==&#039;Peter&#039;}&lt;br /&gt;
|-&lt;br /&gt;
|C||Array (Yes/Uncertain/No) Radio-Buttons||Q10||1-5||Y,N,U|| ||{Q10_1}||{Q10_1.shown}||{Q10_3==&#039;Y&#039;}&lt;br /&gt;
|-&lt;br /&gt;
|X||Boilerplate Question||Q11|| || || || ||{Q11.shown}||&lt;br /&gt;
|-&lt;br /&gt;
|D||Date||Q12|| || || ||{Q12}||{Q12.shown}||&lt;br /&gt;
|-&lt;br /&gt;
|*||Equation||Q13|| || || ||{Q13}||{Q13.shown}||{Q13&amp;gt;5}&lt;br /&gt;
|-&lt;br /&gt;
|~124~||File Upload (records number of files uploaded)||Q14|| || || ||{Q14}|| ||{Q14&amp;gt;0}&lt;br /&gt;
|-&lt;br /&gt;
|G||Gender Drop-Down List||Q15|| ||M,F|| ||{Q15}||{Q15.shown}||{Q15==&#039;M&#039;}&lt;br /&gt;
|-&lt;br /&gt;
|U||Huge Free Text||Q16|| || || ||{Q16}||{Q16.shown}||{strlen(Q16)&amp;gt;100}&lt;br /&gt;
|-&lt;br /&gt;
|I||Language Question||Q17|| || || ||{Q17}||{Q17.shown}||{Q17==&#039;en&#039;}&lt;br /&gt;
|-&lt;br /&gt;
|!||List - Dropdown||Q18|| ||1-5|| ||{Q18}||{Q18.shown}||{Q18==3}&lt;br /&gt;
|-&lt;br /&gt;
|L||List Drop-Down/Radio-Button List||Q19|| ||A-Z|| ||{Q19}||{Q19.shown}||{Q19==&#039;X&#039;}&lt;br /&gt;
|-&lt;br /&gt;
|O||List With Comment Drop-Down/Radio-Button List + Textarea||Q20|| ||A-F|| ||{Q20},{Q20comment}||{Q20.shown}||{Q20==&#039;B&#039;}&lt;br /&gt;
|-&lt;br /&gt;
|T||Long Free Text||Q21|| || || ||{Q21}||{Q21.shown}||{strstr(Q21,&#039;hello&#039;)&amp;gt;0}&lt;br /&gt;
|-&lt;br /&gt;
|M||Multiple Choice Checkbox||Q22||A-F, other|| || ||{Q22_E}, {Q22_other}||{Q22_E.shown}, {Q22_other}||{Q22_E==&#039;Y&#039;}&lt;br /&gt;
|-&lt;br /&gt;
|P||Multiple Choice With Comments Checkbox + Text||Q23||A-F|| || ||{Q23_D}, {Q23_Dcomment}||{Q23_D.shown}||{!is_empty(Q23)}&lt;br /&gt;
|-&lt;br /&gt;
|K||Multiple Numerical Question||Q24||self,mom,dad|| || ||{Q24_self}||{Q24_self.shown}||{Q24_self&amp;gt;30}&lt;br /&gt;
|-&lt;br /&gt;
|Q||Multiple Short Text||Q25||A-F|| || ||{Q25_B}||{Q25_B.shown}||{substr(Q25_B,1,1)==&#039;Q&#039;}&lt;br /&gt;
|-&lt;br /&gt;
|N||Numerical Question Type||Q26|| || || ||{Q26}||{Q26.shown}||{Q26 &amp;gt; 30}&lt;br /&gt;
|-&lt;br /&gt;
|R||Ranking Style||Q27||1-4|| || ||{Q27_1}||{Q27_1.shown}||{Q27_1==3}&lt;br /&gt;
|-&lt;br /&gt;
|S||Short Free Text||Q28|| || || ||{Q28}||{Q28.shown}||{Q28==&#039;mine&#039;}&lt;br /&gt;
|-&lt;br /&gt;
|Y||Yes/No Radio-Buttons||Q29|| || || ||{Q29}||{Q29.shown}||{Q29==&#039;Y&#039;}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==The reserved &#039;this&#039;, &#039;self&#039;, and &#039;that&#039; variables== &amp;lt;!--T:157--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:158--&amp;gt;&lt;br /&gt;
Quite often, you want to evalute all parts of a question, such as counting how many sub-questions have been answered, or summing the scores.  Other times, you want to process just certain rows or columns of a question (such as getting the row or column sums and storing them in the database).  These reserved variables make that process relatively painless.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:159--&amp;gt;&lt;br /&gt;
The &#039;this&#039; variable is used exclusively within the &amp;quot;Whole question validation equation&amp;quot; and &amp;quot;Sub-question validation equation&amp;quot; advanced question options.  It expands to the variable names of each of the cells within those questions.  So, if you want to make sure that each entry is greater than three, you would set the &amp;quot;Sub-question validation equation&amp;quot; to (this &amp;gt; 3).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:160--&amp;gt;&lt;br /&gt;
The &#039;self&#039; and &#039;that&#039; variable are more powerful, and serve as macros which are expanded prior to processing equations.  The syntax choices are:&lt;br /&gt;
*self&lt;br /&gt;
*self.&#039;&#039;suffix&#039;&#039;&lt;br /&gt;
*self.&#039;&#039;sub-selector&#039;&#039;&lt;br /&gt;
*self.&#039;&#039;sub-selector&#039;&#039;.&#039;&#039;suffix&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:161--&amp;gt;&lt;br /&gt;
&#039;&#039;suffix&#039;&#039; is any of the normal qcode suffixes (e.g. NAOK, value, shown)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:162--&amp;gt;&lt;br /&gt;
&#039;&#039;sub-selector&#039;&#039; is one of:&lt;br /&gt;
*comments - only subquestions that are comments (e.g. from multiple choice with comment and list with comment)&lt;br /&gt;
*nocomments - only subquestions that are not comments&lt;br /&gt;
*sq_X - where X is a row or column identifier.  Only sub-questions matching pattern X are selected. Note that search is done on complete code identifier, then sq_X match and include subquestions nX, X, Xn (e.g. if you use sq_1, subquestions a1, 1a, 1, 11 or 001 was included). Put attention at dual scale question type where subquestions code are QCODE_SQCODE_1 and QCODE_SQCODE_1 and to ranking question type where subquestions code are QCODE_1,QCODE_2 ....&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:163--&amp;gt;&lt;br /&gt;
Examples:&lt;br /&gt;
*Has any part of a question been answered?  {count(self.NAOK)&amp;gt;0}&lt;br /&gt;
*What is the assessment score for this question?  {sum(self.value)}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:164--&amp;gt;&lt;br /&gt;
You can also use these to get row and column totals.  Say you have a array of numbers with rows A-E and columns 1-5.&lt;br /&gt;
*What is the grand total?  {sum(self.NAOK)}&lt;br /&gt;
*What is the total of row B?  {sum(self.sq_B.NAOK)}&lt;br /&gt;
*What is the total of column 3? {sum(self.sq_3.NAOK)}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:165--&amp;gt;&lt;br /&gt;
The &#039;that&#039; variable is like the &#039;self&#039; variable, but lets you refer to other questions.  Its syntax is:&lt;br /&gt;
*that.&#039;&#039;qname&#039;&#039;&lt;br /&gt;
*that.&#039;&#039;qname&#039;&#039;.&#039;&#039;suffix&#039;&#039;&lt;br /&gt;
*that.&#039;&#039;qname&#039;&#039;.&#039;&#039;sub-selector&#039;&#039;&lt;br /&gt;
*that.&#039;&#039;qname&#039;&#039;.&#039;&#039;sub-selector&#039;&#039;.&#039;&#039;suffix&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:166--&amp;gt;&lt;br /&gt;
&#039;&#039;qname&#039;&#039; is the question name without any sub-question extensions.  So, say you create a question &#039;q1&#039;, that is its &#039;&#039;qname&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:167--&amp;gt;&lt;br /&gt;
Examples:&lt;br /&gt;
*Has any part of question q1 been answered?  {count(that.q1.NAOK)&amp;gt;0}&lt;br /&gt;
*What is the assessment score for q2?  {sum(that.q2.NAOK)}&lt;br /&gt;
*What is the grand total of q3? {sum(that.q3.NAOK)}&lt;br /&gt;
*What is the total of row C in q4?  {sum(that.q4.sq_C.NAOK)}&lt;br /&gt;
*What is the total of column 2 in q4? {sum(that.q4.sq_2.NAOK)}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:168--&amp;gt;&lt;br /&gt;
The &#039;self&#039; and &#039;that&#039; variables can be used in any relevance,  validation, or tailoring.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:169--&amp;gt;&lt;br /&gt;
The one caveat is that when you use the [[Show Logic File|Show Logic File]] feature, it will show you the expanded value of &#039;self&#039; and &#039;that&#039;.  This lets you see the actual equation that will be generated so that you (and Expression Manager) can validate that the variables exist.  This may seem confusing since you may see quite lenghty equations.  However, if you edit the question, you will see the original equation using &#039;self&#039; and/or &#039;that&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:170--&amp;gt;&lt;br /&gt;
Also note that you should not use these variables if (a) you want to explicitly name each variable used in an equation, or (b) use variables that do not have sub-questions (e.g. single response questions).  In those cases, prefixing a variable with &#039;that&#039; is overkill, and you run the risk of getting unexpected results.&lt;br /&gt;
&lt;br /&gt;
==Usage of NAOK== &amp;lt;!--T:218--&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:219--&amp;gt;&lt;br /&gt;
When you put some variable from question in any equation : if this question (or subquestion) is hidden by condition : this disable all equation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:220--&amp;gt;&lt;br /&gt;
For example : count(Q1_SQ1,Q1_SQ2,Q1_SQ3,Q1_SQ4) give always an empty string if one subquestion of Q1 is filtered.&lt;br /&gt;
To count the number of checked subquestion in such question can be count(Q1_SQ1.NAOK,Q1_SQ2.NAOK,Q1_SQ3.NAOK,Q1_SQ4.NAOK). If the sub question is hidden :Expression manager return an empty string.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:221--&amp;gt;&lt;br /&gt;
Without NAOK : if one question or one subquestion is hidden : Expression Manager return always an empty string, same to return false.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:222--&amp;gt;&lt;br /&gt;
The .shown always use the NAOK system (empty string if hidden) but if you need the code of the answer : it&#039;s always a good idea to add .NAOK after the question code. Except if you need it and know what you do.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:223--&amp;gt;&lt;br /&gt;
Another example and information is provided at [[#Overriding_Cascading_Conditions|Overriding Cascading Conditions]]&lt;br /&gt;
&lt;br /&gt;
==Access to Functions== &amp;lt;!--T:171--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:172--&amp;gt;&lt;br /&gt;
Expression Manager provides access to mathematical, string, and user-defined functions, as shown below.  It has PHP and JavaScript equivalents for these functions so that they work identically on server-side (PHP) and client-side (JavaScript).  It is easy to add new functions.&lt;br /&gt;
&lt;br /&gt;
===Implemented Functions=== &amp;lt;!--T:173--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:174--&amp;gt;&lt;br /&gt;
The following functions are currently available:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:175--&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Function!!Meaning!!Syntax&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.abs.php abs]||Absolute value||number abs(number)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.acos.php acos]||Arc cosine||number acos(number)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.addslashes.php addslashes]||Quote string with slashes||string addslashes(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.asin.php asin]||Arc sine||number asin(number)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.atan.php atan]||Arc tangent||number atan(number)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.atan2.php atan2]||Arc tangent of two variables||number atan2(number, number)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.ceil.php ceil]||Round fractions up||number ceil(number)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.checkdate.php checkdate]||Returns true(1) if it is a valid date in gregorian calendar||bool checkdate(month,day,year)&lt;br /&gt;
|-&lt;br /&gt;
|convert_value||Convert a numerical value using a inputTable and outputTable of numerical values||number convert_value(fValue, iStrict, sTranslateFromList, sTranslateToList)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.cos.php cos]||Cosine||number cos(number)&lt;br /&gt;
|-&lt;br /&gt;
|count||count the number of answered (non-blank)questions in the list||number count(arg1, arg12, ..., argN)&lt;br /&gt;
|-&lt;br /&gt;
|countif||Count the number of answered questions in the list equal the first argument||number countif(matches, arg1, arg2, ... argN)&lt;br /&gt;
|-&lt;br /&gt;
|countifop||Count the number of answered questions in the list which pass the criteria (arg op value)||number countifop(op, value, arg1, arg2, ... argN)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.date.php date]||Format a local date/time||string date(format &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;, timestamp=time()])&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.exp.php exp]||Calculates the exponent of e||number exp(number)&lt;br /&gt;
|-&lt;br /&gt;
|fixnum||Display numbers with comma as radix separator, if needed||string fixnum(number)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.floor.php floor]||Round fractions down||number floor(number)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.gmdate.php gmdate]||Format a GMT date/time||string gmdate(format &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;, timestamp=time()])&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.html-entity-decode.php html_entity_decode]||Convert all HTML entities to their applicable characters (always uses ENT_QUOTES and UTF-8)||string html_entity_decode(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.htmlentities.php htmlentities]||Convert all applicable characters to HTML entities (always uses ENT_QUOTES and UTF-8)||string htmlentities(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.htmlspecialchars.php expr_mgr_htmlspecialchars]||Convert special characters to HTML entities (always uses ENT_QUOTES and UTF-8)||string htmlspecialchars(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.htmlspecialchars-decode.php expr_mgr_htmlspecialchars_decode]||Convert special HTML entities back to characters (always uses ENT_QUOTES and UTF-8)||string htmlspecialchars_decode(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.idate.php idate]||Format a local time/date as integer||string idate(string &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;, timestamp=time()])&lt;br /&gt;
|-&lt;br /&gt;
|if||Excel-style if(test,result_if_true,result_if_false)||if(test,result_if_true,result_if_false)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.implode.php implode]||Join array elements with a string||string implode(glue,arg1,arg2,...,argN)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.intval.php intval]||Get the integer value of a variable||int intval(number &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;, base=10])&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.empty.php is_empty]||Determine whether a variable is considered to be empty||bool is_empty(var)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.is-float.php is_float]||Finds whether the type of a variable is float||bool is_float(var)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.is-int.php is_int]||Find whether the type of a variable is integer||bool is_int(var)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.is-nan.php is_nan]||Finds whether a value is not a number||bool is_nan(var)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.is-null.php is_null]||Finds whether a variable is NULL||bool is_null(var)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.is-numeric.php is_numeric]||Finds whether a variable is a number or a numeric string||bool is_numeric(var)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.is-string.php is_string]||Find whether the type of a variable is string||bool is_string(var)&lt;br /&gt;
|-&lt;br /&gt;
|join{{NewIn|2.0|b=130129}}||Join elements as a new string||join(arg1, arg2, ... argN)&lt;br /&gt;
|-&lt;br /&gt;
|list||Return comma-separated list of non-blank values||string list(arg1, arg2, ... argN)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.log.php log]|| The logarithm of number to base, if given, or the natural logarithm. ||number log(number,base=e)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.ltrim.php ltrim]||Strip whitespace (or other characters) from the beginning of a string||string ltrim(string &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;, charlist])&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.max.php max]||Find highest value||number max(arg1, arg2, ... argN)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.min.php min]||Find lowest value||number min(arg1, arg2, ... argN)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.mktime.php mktime]||Get UNIX timestamp for a date (each of the 6 arguments are optional)||number mktime([hour [, minute [, second [, month [, day [, year ]]]]]])&lt;br /&gt;
|-&lt;br /&gt;
|modulo-function||The modulo function is &#039;&#039;&#039;not supported&#039;&#039;&#039; yet. You can use the floor() function instead||floor(x/y)==(x/y)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.nl2br.php nl2br]||Inserts HTML line breaks before all newlines in a string||string nl2br(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.number-format.php number_format]||Format a number with grouped thousands||string number_format(number)&lt;br /&gt;
|-&lt;br /&gt;
|pi||Get value of pi||number pi()&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.pow.php pow]||Exponential expression||number pow(base, exp)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.quoted-printable-decode.php quoted_printable_decode]||Convert a quoted-printable string to an 8 bit string||string quoted_printable_decode(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.quoted-printable-encode.php quoted_printable_encode]||Convert a 8 bit string to a quoted-printable string||string quoted_printable_encode(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.quotemeta.php quotemeta]||Quote meta characters||string quotemeta(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.rand.php rand]||Generate a random integer, see [[Expression Manager Sample Surveys#Randomly Ask One Question Per Group|this example]]||int rand() OR int rand(min, max)&lt;br /&gt;
|-&lt;br /&gt;
|regexMatch||compare a string to a [[Using regular expressions|regular expression]]||bool regexMatch(pattern,input)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.round.php round]||Rounds a number to an optional precision||number round(val &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;, precision])&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.rtrim.php rtrim]||Strip whitespace (or other characters) from the end of a string||string rtrim(string &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;, charlist])&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.sin.php sin]||Sine||number sin(arg)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.sprintf.php sprintf]||Return a formatted string||string sprintf(format, arg1, arg2, ... argN)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.sqrt.php sqrt]||Square root||number sqrt(arg)&lt;br /&gt;
|-&lt;br /&gt;
|stddev||Calculate the Sample Standard Deviation for the list of numbers||number stddev(arg1, arg2, ... argN)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.str-pad.php str_pad]||Pad a string to a certain length with another string||string str_pad(input, pad_length &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;, pad_string])&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.str-repeat.php str_repeat]||Repeat a string||string str_repeat(input, multiplier)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.str-replace.php str_replace]||Replace all occurrences of the search string with the replacement string||string str_replace(search, replace, subject)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.strcasecmp.php strcasecmp]||Binary safe case-insensitive string comparison||int strcasecmp(str1, str2)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.strcmp.php strcmp]||Binary safe string comparison||int strcmp(str1, str2)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.strip-tags.php strip_tags]||Strip HTML and PHP tags from a string||string strip_tags(str, allowable_tags)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.stripos.php stripos]||Find position of first occurrence of a case-insensitive unicode string (starting by 0, return false if not found)|||int stripos(haystack, needle &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;, offset=0])&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.stripslashes.php stripslashes]||Un-quotes a quoted string||string stripslashes(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.stristr.php stristr]||Case-insensitive strstr||string stristr(haystack, needle &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;, before_needle=false])&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.strlen.php strlen]||Get string length||int strlen(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.strpos.php strpos]||Find position of first occurrence of an unicode string (starting by 0, return false if not found)||int strpos(haystack, needle &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt; offset=0])&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.strrev.php strrev]||Reverse a string||string strrev(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.strstr.php strstr]||Find first occurrence of a string||string strstr(haystack, needle&amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;, before_needle=false])&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.strtolower.php strtolower]||Make a string lowercase||string strtolower(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.strtotime.php strtotime]||Parse about any English textual datetime description into a Unix timestamp||int strtotime(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.strtoupper.php strtoupper]||Make a string uppercase||string strtoupper(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.substr.php substr]||Return part of an unicode string||string substr(string, start &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;, length])&lt;br /&gt;
|-&lt;br /&gt;
|sum||Calculate the sum of values in an array||number sum(arg1, arg2, ... argN)&lt;br /&gt;
|-&lt;br /&gt;
|sumifop||Sum the values of answered questions in the list which pass the criteria (arg op value)||number sumifop(op, value, arg1, arg2, ... argN)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.tan.php tan]||Tangent||number tan(arg)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.time.php time]||Return current UNIX timestamp||number time()&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.trim.php trim]||Strip whitespace (or other characters) from the beginning and end of a string||string trim(string &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;, charlist])&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.ucwords.php ucwords]||Uppercase the first character of each word in a string||string ucwords(string)&lt;br /&gt;
|-&lt;br /&gt;
|unique||Returns true if all non-empty responses are unique||boolean unique(arg1, ..., argN)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Functions that are Planned or Being Considered=== &amp;lt;!--T:176--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:177--&amp;gt;&lt;br /&gt;
Other functions that are planned (or being considered) but which are not implemented yet include the following.  Some of these are for backwards compatability with another survey tool.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:178--&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Syntax!!Meaning!!Comments&lt;br /&gt;
|-&lt;br /&gt;
|e()||returns the value of e||&lt;br /&gt;
|-&lt;br /&gt;
|formatDate(X,PAT)||return the string value of date X formatted according to Java data format pattern PAT||&lt;br /&gt;
|-&lt;br /&gt;
|formatNumber(X,PAT)||return the string value of number X formatted according to Java number format pattern PAT||&lt;br /&gt;
|-&lt;br /&gt;
|getAnsOption(X)||returns the text corresponding to the selected option for answer X||this is the same as X.shown&lt;br /&gt;
|-&lt;br /&gt;
|getAnsOption(X,Y)||returns the text corresponding to the option at index Y of node X||&lt;br /&gt;
|-&lt;br /&gt;
|getRelevance(X)||returns the relevance equation for question X||&lt;br /&gt;
|-&lt;br /&gt;
|getStartTime()||returns the date corresponding to the system time when the interview was started||&lt;br /&gt;
|-&lt;br /&gt;
|getType(X)||returns the string name of the datatype - e.g. *NA* if isNA()||&lt;br /&gt;
|-&lt;br /&gt;
|gotoFirst()||jumps to the first relevant set of questions - this violates the normal flow of the system||&lt;br /&gt;
|-&lt;br /&gt;
|gotoNext()||jumps to the next set of relevant questions - this violates the normal flow of the system||&lt;br /&gt;
|-&lt;br /&gt;
|gotoPrevious()||jumps to the previous set of relevant questions - this violates the normal flow of the system||&lt;br /&gt;
|-&lt;br /&gt;
|isAsked(X)||returns true if the answer is neither *NA*, *INVALID*, nor *UNASKED*||&lt;br /&gt;
|-&lt;br /&gt;
|isInvalid(X)||returns true if the answer is of type *INVALID*||&lt;br /&gt;
|-&lt;br /&gt;
|isNA(X)||returns true if the answer is of type *NA*||&lt;br /&gt;
|-&lt;br /&gt;
|isNotUnderstood(X)||returns true if the answer if of type *HUH*||&lt;br /&gt;
|-&lt;br /&gt;
|isRefused(X)||returns true if the answer is of type *REFUSED*||&lt;br /&gt;
|-&lt;br /&gt;
|isSpecial(X)||returns true if the answer is of type *UNASKED*, *NA*, *REFUSED*, *INVALID*, *UNKNOWN*, or *HUH*||&lt;br /&gt;
|-&lt;br /&gt;
|isUnknown(X)||returns true if the answer is of type *UNKNOWN*||&lt;br /&gt;
|-&lt;br /&gt;
|jumpTo(X)||jump to the group containing the named question -- this violates the normal flow of the system||&lt;br /&gt;
|-&lt;br /&gt;
|jumpToFirstUnasked()||jump to the first unasked question &amp;lt;strike&amp;gt; thus bypassing previous answered questions &amp;lt;/strike&amp;gt; this violates the normal flow of the system||&lt;br /&gt;
|-&lt;br /&gt;
|lastIndexOf(X,Y)||returns the last index (base 0) of string Y in string X. Returns -1 if Y is not contained within X||&lt;br /&gt;
|-&lt;br /&gt;
|list(X,...)||a string containing a comma separated list of the positive values with &amp;quot;and&amp;quot; separating the last two||&lt;br /&gt;
|-&lt;br /&gt;
|mean(X,...)||returns the mean of a list of values||&lt;br /&gt;
|-&lt;br /&gt;
|numAnsOptions(X)||returns the number of answer options that question X has||&lt;br /&gt;
|-&lt;br /&gt;
|orlist(X,...)||a string containing a comma separated list of the positive values, with &amp;quot;or&amp;quot; separting the last two||&lt;br /&gt;
|-&lt;br /&gt;
|parseDate(X,PAT)||returns the date value of string X parsed with Java date format pattern PAT||&lt;br /&gt;
|-&lt;br /&gt;
|parseNumber(X,PAT)||returns the numerical value of string X parsed with Java number format pattern PAT||&lt;br /&gt;
|-&lt;br /&gt;
|showAllResponsesExcept( questionList,attributeList,attributeTitleList)||questionList = pipe-delimited list of question identifiers; attributeList = pipe-delimited list of attributes (like question#, title, text, type - so you can decide what to show); attributeTitleList = pipe-delimited list of table headers, so can internationalize the report.||&lt;br /&gt;
|-&lt;br /&gt;
|showTheseResponses( questionList,attributeList,attributeTitleList)||questionList = pipe-delimited list of question identifiers; attributeList = pipe-delimited list of attributes (like question#, title, text, type - so you can decide what to show); attributeTitleList = pipe-delimited list of table headers, so can internationalize the report.|| &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Expression Manager Knows Which Variables are Local== &amp;lt;!--T:179--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:180--&amp;gt;&lt;br /&gt;
In order to properly build the JavaScript for page, Expression Manager needs to know which variables are set on the page, and what their JavaScript ID is (e.g. for document.getElementById(x)).  It also must know which variables are set on other pages (so that it can ensure that the needed &amp;lt;input type=&#039;hidden&#039; value=&#039;x&#039;&amp;gt; fields are present and populated).&lt;br /&gt;
&lt;br /&gt;
==Cascading Conditions== &amp;lt;!--T:181--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:182--&amp;gt;&lt;br /&gt;
If any of the variables are irrelevant, the whole equation will be irrelevant (false).  For example, in the following table, N/A means that one of the variables was not relevant&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:183--&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Operator!!Example!!a!!b!!Result&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;+ (unary)&amp;lt;/nowiki&amp;gt;||&amp;lt;nowiki&amp;gt;+a&amp;lt;/nowiki&amp;gt;||N/A|| ||false&lt;br /&gt;
|-&lt;br /&gt;
|- (unary)||-a||N/A|| ||false&lt;br /&gt;
|-&lt;br /&gt;
|!||!a||N/A|| ||false&lt;br /&gt;
|-&lt;br /&gt;
|== (or eq)||a == b||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|== (or eq)||a == b||N/A||0||false&lt;br /&gt;
|-&lt;br /&gt;
|== (or eq)||a == b||N/A||N/A||false&lt;br /&gt;
|-&lt;br /&gt;
|!= (or ne)||a != b||N/A||5|| false&lt;br /&gt;
|-&lt;br /&gt;
|!= (or ne)||a != b||N/A||N/A|| false&lt;br /&gt;
|-&lt;br /&gt;
|!= (or ne)||a != b||N/A||0||false&lt;br /&gt;
|-&lt;br /&gt;
|&amp;gt; (or gt)||a &amp;gt; b||N/A||5|| false&lt;br /&gt;
|-&lt;br /&gt;
|&amp;gt;= (or ge)||a &amp;gt;= b||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt; (or lt)||a &amp;lt; b||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;= (or le)||a &amp;lt;= b||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|and||a and b||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|and||a and b||N/A||N/A||false&lt;br /&gt;
|-&lt;br /&gt;
|or||a or b||N/A||N/A||false&lt;br /&gt;
|-&lt;br /&gt;
|or||a or b||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;+&amp;lt;/nowiki&amp;gt;||a + b||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|-||a - b||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|*||a * b||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|/||a / b||5||N/A||false&lt;br /&gt;
|-&lt;br /&gt;
|()||(a)||N/A|| ||false&lt;br /&gt;
|-&lt;br /&gt;
|(exp)||(a &amp;amp;&amp;amp; b)||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|(exp) op (exp)||(b + b) &amp;gt; (a &amp;amp;&amp;amp; b)||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|function||sum(a,b,b)||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|function||max(a,b)||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|function||min(a,b)||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|function||implode(&#039;, &#039;,a,b,a,b)||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|function||if(a,a,b)||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|function||is_empty(a)||N/A|| ||false&lt;br /&gt;
|-&lt;br /&gt;
|function||is_empty(a)||0 (or blank)|| ||true&lt;br /&gt;
|-&lt;br /&gt;
|function||!is_empty(a)||N/A|| ||false&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Overriding Cascading Conditions=== &amp;lt;!--T:184--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:185--&amp;gt;&lt;br /&gt;
Say you want to show a running total of all relevant answers.  You might try to use the equation {sum(q1,q2,q3,...,qN)}.  However, this gets translated internally to LEMif(LEManyNA(&#039;q1&#039;,&#039;q2&#039;,&#039;q3&#039;,...,&#039;qN&#039;),&#039;&#039;,sum(LEMval(&#039;q1&#039;),LEMval(&#039;q2&#039;),LEMval(&#039;q3&#039;),...,LEMval(&#039;qN&#039;))).  So, if any of the values q1-qN are irrelevant, the equation will always return false.  In this case, the sum() will show 0 until all questions are answered.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:186--&amp;gt;&lt;br /&gt;
To get around this, each variable can have a &amp;quot;.NAOK&amp;quot; suffix (meaning that Not Applicable is OK) added to it.  In such cases, the following behavior occurs.  Say you have a variable q1.NAOK&lt;br /&gt;
#q1 is not added to the LEManyNA() clause&lt;br /&gt;
#LEMval(&#039;q1&#039;) will  continue to check whether the response is relevant, and will return &amp;lt;nowiki&amp;gt;&#039;&#039;&amp;lt;/nowiki&amp;gt; if it is not (so individual irrelevant responses will be ignored, but they will not void the entire expression).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:187--&amp;gt;&lt;br /&gt;
So, the solution to the running total problem is to use the equation sum(q1.NAOK,q2.NAOK,q3.NAOK,...,qN.NAOK).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:188--&amp;gt;&lt;br /&gt;
The use of the .NAOK suffix also lets authors design surveys that have several possible paths but then converge on common paths later.  For example, say subjects answer a survey in a way that is outside the normal range of responses.  The author could alert the subjects that they may not get valid results, and ask them whether they really want to  continue with the survey.  If they say Yes, then the rest of the questions will be shown.  The condition for the &amp;quot;rest of the questions&amp;quot; would check whether the initial responses were answered within the normal range OR whether the subject said Yes to the question that is only relevant if they answered outside the normal range.&lt;br /&gt;
&lt;br /&gt;
==How does Expression Manager Support Conditional Micro-Tailoring?== &amp;lt;!--T:189--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:190--&amp;gt;&lt;br /&gt;
Here is an example of micro-tailoring (where Question Type==&#039;expr&#039; means an Equation):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:191--&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Question Code!!Relevance!!Question Type!!Question&lt;br /&gt;
|-&lt;br /&gt;
|name||1||text||What is your name?&lt;br /&gt;
|-&lt;br /&gt;
|age||1||text||How old are you?&lt;br /&gt;
|-&lt;br /&gt;
|badage||!is_empty(age)||expr||{(age&amp;lt;16) or (age&amp;gt;80)}&lt;br /&gt;
|-&lt;br /&gt;
|agestop||badage||message||Sorry, {name}, you are too {if( (age&amp;lt;16),&#039;young&#039;,if( (age&amp;gt;80),&#039;old&#039;,&#039;middle-aged&#039;) ) } for this test.&lt;br /&gt;
|-&lt;br /&gt;
|kids||!badage||yesno||Do you have children?&lt;br /&gt;
|-&lt;br /&gt;
|parents||1||expr||{!badage &amp;amp;&amp;amp; kids==&#039;Y&#039;}&lt;br /&gt;
|-&lt;br /&gt;
|numKids||parents||text||How many children do you have?&lt;br /&gt;
|-&lt;br /&gt;
|kid1||parents &amp;amp;&amp;amp; numKids &amp;gt;= 1||text||How old is your first child?&lt;br /&gt;
|-&lt;br /&gt;
|kid2||parents &amp;amp;&amp;amp; numKids &amp;gt;= 2||text||How old is your second child?&lt;br /&gt;
|-&lt;br /&gt;
|kid3||parents &amp;amp;&amp;amp; numKids &amp;gt;= 3||text||How old is your third child?&lt;br /&gt;
|-&lt;br /&gt;
|kid4||parents &amp;amp;&amp;amp; numKids &amp;gt;= 4||text||How old is your fourth child?&lt;br /&gt;
|-&lt;br /&gt;
|kid5||parents &amp;amp;&amp;amp; numKids &amp;gt;= 5||text||How old is your fifth child?&lt;br /&gt;
|-&lt;br /&gt;
|sumage||1||expr||{sum(kid1.NAOK,kid2.NAOK,kid3.NAOK,kid4.NAOK,kid5.NAOK)}&lt;br /&gt;
|-&lt;br /&gt;
|report||parents||yesno||{name}, you said you are {age} and that you have {numKids}.  The sum of ages of your first {min(numKids,5)} kids is {sumage}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:192--&amp;gt;&lt;br /&gt;
All of these questions can be on a single page (e.g. in the same group), and only the relevant questions will display.  Moreover, as you enter the ages of children, the sum() expression in the last question will dynamically update on the page.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:193--&amp;gt;&lt;br /&gt;
Expression Manager provides this functionality by surrounding each expression with a named &amp;lt;span&amp;gt; element.  Every time a value changes, it recomputes the expression that should appear in that &amp;lt;span&amp;gt; element and regenerates the display.  You can have dozens, or even hundreds, of such tailored expressions on the same page, and the page will re-display all of them in a single screen refresh.&lt;br /&gt;
&lt;br /&gt;
==Mapping of LimeSurvey 1.91+ to Expression Manager Functionality== &amp;lt;!--T:194--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:195--&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Old Feature!!New Feature!!Comments&lt;br /&gt;
|-&lt;br /&gt;
|Conditions||Relevance||You can use very complex conditional equations, and access a broader range of variables&lt;br /&gt;
|-&lt;br /&gt;
|Assessments||Equation||Any assessment scores can be re-structured into an Equation. This both ensures that the score is written to the database, and also lets you see dynamic changes to the score value on the current page&lt;br /&gt;
|-&lt;br /&gt;
|Replacements||Expression Manager||The core engine takes the input string and treats everything within curly braces as an Expression - so it handles all historical replacements types.  To avoid messing up embedded JavaScript, Expression Manager only processes content between curly braces as long as (a)  there is no leading or trailing whitespace within the curly braces - e.g. {expr} is an expression, but { expr}, {expr }, and { expr } are not expressions.  Furthermore, Expression Manager does not process content within its own strings (e.g. {list(&#039;hi&#039;,&#039;there {braces}&#039;)} generates &amp;quot;hi there {braces}&amp;quot;).  It also ignores escaped curly braces (e.g. \{this is not an expression\})&lt;br /&gt;
|-&lt;br /&gt;
|Validation||Expression Manager||The plan is to take the current min/max Question Attributes and have Expression Manager process them.  That way the min/max values can be expressions themselves&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Syntax Highlighting= &amp;lt;!--T:196--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:197--&amp;gt;&lt;br /&gt;
To help with entering and validating expressions, EM provides syntax highlighting with the following features:&lt;br /&gt;
&lt;br /&gt;
==Types and Meanings of Syntax Highlighting== &amp;lt;!--T:198--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:199--&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Color!!Sample!!Meaning!!Tooltip!!Comments&lt;br /&gt;
|-&lt;br /&gt;
|tan background||style=&#039;background-color: #eee8aa&#039;|Sample||the whole equation||none||Anything within curly braces that is recognized as an equation (e.g. there is no leading or trailing whitepace) will be color-coded with a tan background to help distinguish it from surrounding text&lt;br /&gt;
|-&lt;br /&gt;
|bold red text||style=&#039;color:#ff0000; background-color:#eee8aa&#039;|&#039;&#039;&#039;Sample&#039;&#039;&#039;||An error||Some explanation on error||Can be an unknow variable or an error in function, .... Survey can be totally broken, this don&#039;t show to public user.&lt;br /&gt;
|-&lt;br /&gt;
|blue text||style=&#039;color:#0000ff; background-color:#eee8aa&#039;|Sample||function name||meaning and allowable syntax||function names, or things that should be functions since they are followed by an opening parenthesis, are presented in bold blue text.  Tooltips show the meaning and allowable syntax for the function.&lt;br /&gt;
|-&lt;br /&gt;
|grey text||style=&#039;color:#808080; background-color:#eee8aa&#039;|Sample||string||none||single and double-quoted strings are shown in grey text&lt;br /&gt;
|-&lt;br /&gt;
|cyan text||style=&#039;color:#4169e1; background-color:#eee8aa&#039;|Sample||variable set on the same page,||&amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;name or SGQA code]: question; value; answerList showing codes for each value||Any variable that is set on the same page to the current question is shown in cyan text, showning it can be updated in javascript.  The tooltip shows its name (if you used INSERTANS:xxx) or SGQA code (if you used the new naming system), the actual question, and its current value (or blank if not set).  If the question type expects responses from an enumerated value set, the mapping of the codes to display values is show.&lt;br /&gt;
|-&lt;br /&gt;
|green text||style=&#039;color:#008000; background-color:#eee8aa&#039;|Sample||variable set on a prior page||&amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;name or SGQA code]: question; value; answerList showing codes for each value||Any variable that is set on a prior page is shown in bold green text.  The tooltip shows its name (if you used INSERTANS:xxx) or SGQA code (if you used the new naming system), the actual question, and its current value (or blank if not set).  If the question type expects responses from an enumerated value set, the mapping of the codes to display values is show.&lt;br /&gt;
|-&lt;br /&gt;
|bold pink text||style=&#039;color:#9370db; background-color:#eee8aa&#039;|Sample||variable set on a later page &amp;lt;sup&amp;gt;in general : empty at survey start, but can be filled with index or move previous&amp;lt;/sup&amp;gt;||&amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;name or SGQA code]: question; value; answerList showing codes for each value||Any variable that is set on a prior page is shown in bold pink text.  These are erorrs since the variable is  being used before it is declareed.  The tooltip shows its name (if you used INSERTANS:xxx) or SGQA code (if you used the new naming system), the actual question, and its current value (or blank if not set).  If the question type expects responses from an enumerated value set, the mapping of the codes to display values is show.&lt;br /&gt;
|-&lt;br /&gt;
|bold tan text||style=&#039;color:#a0522d; background-color:#eee8aa&#039;|Sample||a lime replacement value||the value||Lime Replacement Strings (like {TOKEN:xxx}, {PRIVACY_MESSAGE}) are shown in bold tan text.  &lt;br /&gt;
|-&lt;br /&gt;
|red text||style=&#039;color:#ff4500; background-color:#eee8aa&#039;|Sample||assignment operator (=) ||warning message||If you use one of the assignment operator (=) that operator will be displayed in red text.  This is meant to help prevent accidental re-assignment of values when you really meant to check whether a == b instead of  setting the value of a = b.&lt;br /&gt;
|-&lt;br /&gt;
|normal black text||style=&#039;color:black; background-color:#eee8aa&#039;|Sample||punctuation||none||All other punctuation within the expression is shown as normal black text.&lt;br /&gt;
|-&lt;br /&gt;
|red-boxed text||a bold red line surrounds the error||syntax error||description of the error||Any detected syntax errors are shown by surrounding the error with a red box.  The tooltip shows the error.  Examples include unmatched parentheses, use of undefined functions, passing the wrong number of arguments to functions, poorly structured expressions (e.g. missing operators between variables), trying to assign a new value to a read-only variable, trying to assign values to non-variables, or using unsupported syntax.  Note that the syntax error dectection system may only report one error in an expression even if there are multiple errors; however, if any errors are detected, at least one error will be shown.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Additional Reading= &amp;lt;!--T:202--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==[[Expression Manager Sample Surveys|Expression Manager Sample Surveys]]== &amp;lt;!--T:203--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==[[Expression Manager HowTos|Use Cases and HowTos]]== &amp;lt;!--T:204--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==[[Expression Manager Examples|Step-by-Step Examples]].== &amp;lt;!--T:205--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==[[Expression Manager for developers|Reference for Developers]]== &amp;lt;!--T:206--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==[[Expression Manager Roadmap|RoadMap/Status/ToDo List]]== &amp;lt;!--T:207--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/translate&amp;gt;&lt;/div&gt;</summary>
		<author><name>LimeAJ</name></author>
	</entry>
	<entry>
		<id>https://www.limesurvey.org/manual/index.php?title=Question_signature&amp;diff=73654</id>
		<title>Question signature</title>
		<link rel="alternate" type="text/html" href="https://www.limesurvey.org/manual/index.php?title=Question_signature&amp;diff=73654"/>
		<updated>2017-06-05T18:29:52Z</updated>

		<summary type="html">&lt;p&gt;LimeAJ: /* Question signature */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
=Question signature=&lt;br /&gt;
&lt;br /&gt;
Since question types can no longer be uniquely identified their object names, we have created a signature scheme.&lt;br /&gt;
&lt;br /&gt;
While in a single limesurvey instance question objects must be uniquely named, there might be different plugins defining the question objects with the same name.&lt;br /&gt;
&lt;br /&gt;
To make sure we can identify what the type of a question is, we derive a unique identifier (GUID) from a signature.&lt;br /&gt;
&lt;br /&gt;
Each question object MUST therefore define a protected static $signature field. This field is used to derive the signature using a hashing approach.&lt;br /&gt;
&lt;br /&gt;
It is the developer&#039;s task to make this signature as unique as possible, yet, it MUST never change. If the signature of a question object changes it is recognized as a new question type, while this is not necessarily a problem, the fact that the old question type is no longer available is. Since LimeSurvey cannot find the old question type it will not be able to execute, import, or maybe even edit, surveys containing this now unknown question type.&lt;br /&gt;
&lt;br /&gt;
An example of a signature is shown below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
protected static $signature = array(&lt;br /&gt;
&lt;br /&gt;
   &#039;orignalAuthor&#039; =&amp;gt; &#039;Sam Mousa&#039;,&lt;br /&gt;
&lt;br /&gt;
   &#039;originalName&#039; =&amp;gt; &#039;Yes / No&#039;,&lt;br /&gt;
&lt;br /&gt;
   &#039;startDev&#039; =&amp;gt; &#039;2013-30-1&#039;&lt;br /&gt;
&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that you are free to use any format / data type you want. The GUID is derived using the following code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
* This function derives a unique identifier for identifying a question type.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
public static function getGUID()&lt;br /&gt;
&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
   // We use json_encode because it is faster than serialize.&lt;br /&gt;
&lt;br /&gt;
   return md5(json_encode(static::$signature));&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>LimeAJ</name></author>
	</entry>
	<entry>
		<id>https://www.limesurvey.org/manual/index.php?title=Expression_Manager&amp;diff=73653</id>
		<title>Expression Manager</title>
		<link rel="alternate" type="text/html" href="https://www.limesurvey.org/manual/index.php?title=Expression_Manager&amp;diff=73653"/>
		<updated>2017-05-31T19:58:59Z</updated>

		<summary type="html">&lt;p&gt;LimeAJ: grammar correction&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;languages /&amp;gt; &amp;lt;translate&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:1--&amp;gt;&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:2--&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;simplebox&amp;quot;&amp;gt; Note: This feature is only available in LimeSurvey 1.92 or later. &amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Quick Start Tutorial= &amp;lt;!--T:3--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Overview== &amp;lt;!--T:4--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:5--&amp;gt;&lt;br /&gt;
When customizing your surveys, you typically need a way to specify the following:&lt;br /&gt;
#&#039;&#039;&#039;Navigation/Branching&#039;&#039;&#039; - letting a subject&#039;s answers change the order in which questions are asked&lt;br /&gt;
#&#039;&#039;&#039;Tailoring/Piping&#039;&#039;&#039; - how to phrase the question (such as referring to prior answers, or conjugating sentences based upon the number or gender of your subjects), or how to generate custom reports (like assessment scores or tailored advice).&lt;br /&gt;
#&#039;&#039;&#039;Validation&#039;&#039;&#039; - ensuring that answers pass certain criteria, like min and max values, or matching an input pattern&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:6--&amp;gt;&lt;br /&gt;
Expression Manager (EM) provides an intuitive way to specifying the logic for each of those features.  Nearly anything that you can write as a standard mathematical equation is a valid expression, even if you are calling functions.  EM currently provides access to 70 functions, and can be easily extended to support more.  It also lets you access your variables using human-readable variable names (rather than SGQA names).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:7--&amp;gt;&lt;br /&gt;
The following sections show the main places where Expression Manager is used&lt;br /&gt;
&lt;br /&gt;
==Relevance (Controlling Navigation/Branching)== &amp;lt;!--T:8--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:9--&amp;gt;&lt;br /&gt;
Some surveys use &amp;quot;Goto Logic&amp;quot;, such that if you answer Question 1 with option C, then jump to Question 5. This approach is very limiting, since is hard to validate, and easily breaks if you have to re-order questions.  EM uses a Boolean relevance equation to specify all of the conditions under which a question might be valid.  If the question is relevant, then the question is asked, otherwise it is Not Applicable, and the value NULL is stored in the database.  This is similar to what can be done via the Conditions editor, but EM lets you easily specify much more complex and powerful criteria (and lets you use the variable name rather than SGQA naming).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:10--&amp;gt;&lt;br /&gt;
This image shows one way to review the relevance logic for a survey.  It computes Body Mass Index.  The relevance equation is shown in square bracket right after the variable name (which is in green).  So, the relevance of weight, weight_units, height and height_units are all 1, meaning that those questions are always asked.  However, the relevance for BMI is {!is_empty(height) and !is_empty(weight)}, which means that BMI will only be computed if the subject enters a value for both height and weight (thereby avoiding the risk of a divide by zero error).  Also, the Report question is only shown if the subject answers all four main questions (height, height_units, weight, weight_units).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:11--&amp;gt;&lt;br /&gt;
[[File:tutorial1.jpg]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:12--&amp;gt;&lt;br /&gt;
Relevance is shown and editable in the following places:&lt;br /&gt;
&lt;br /&gt;
===Viewing / Editing Question-Level Relevance=== &amp;lt;!--T:13--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:14--&amp;gt;&lt;br /&gt;
This equation computes the Body Mass Index (BMI).  It is only asked if the person first enters their height and weight.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:15--&amp;gt;&lt;br /&gt;
[[File:tutorial2.jpg]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:16--&amp;gt;&lt;br /&gt;
This is the edit screen for the BMI question.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:17--&amp;gt;&lt;br /&gt;
[[File:tutorial3.jpg]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:18--&amp;gt;&lt;br /&gt;
Note that you do not use the curly braces when you enter a Relevance Equation.&lt;br /&gt;
&lt;br /&gt;
===Viewing / Editing Group-Level Relevance=== &amp;lt;!--T:19--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:20--&amp;gt;&lt;br /&gt;
This is a sample census survey.  The first page asks how many people live with you and stores that in the &amp;quot;cohabs&amp;quot; variable.  This page is only shown if you have more than one cohabitant (so it is shown for the second person cohabitating with you), and also only shows if you specified how Person One is related to you (p1_rel).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:21--&amp;gt;&lt;br /&gt;
[[File:tutorial4.jpg]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:22--&amp;gt;&lt;br /&gt;
As you can see, the group also has question-level relevance criteria, such that each question only appears once you have answered the question before it (e.g. {!is_empty(p1_sex)}).  EM combines the Group and Question-level relevance for you.  Questions in a group are only asked  if the group as a whole is relevant.  Then, only the subset of questions within the group that are relevant are asked.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:23--&amp;gt;&lt;br /&gt;
Here is the screen for editing the group-level relevance for that question:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:24--&amp;gt;&lt;br /&gt;
[[File:tutorial5.jpg]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:25--&amp;gt;&lt;br /&gt;
Note that you do not use the curly braces when you enter a Relevance Equation.&lt;br /&gt;
&lt;br /&gt;
==Tailoring/Piping== &amp;lt;!--T:26--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:27--&amp;gt;&lt;br /&gt;
EM lets you easily do simple and complex conditional tailoring of your questions.  Sometimes you just need simple substitution, like saying, &amp;quot;You said you purchased &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;Product].  What did you like best about it?&amp;quot;.  Sometimes you need conditional substitution like &amp;quot;&amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;Mr./Mrs.] &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;LastName], would you be willing to complete our survey?&amp;quot;.  In this case,  you want to use Mr. or Mrs. based upon the person&#039;s gender.  Other times you need even more complex substitution (such as based upon a mathematical computation).  EM supports each of these types of tailoring/piping.&lt;br /&gt;
&lt;br /&gt;
===Conditional Equations=== &amp;lt;!--T:28--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:29--&amp;gt;&lt;br /&gt;
The Body Mass Index example shows the ability to compute a person&#039;s BMI, even while letting them enter their height in weight in metric or non-metric units.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:30--&amp;gt;&lt;br /&gt;
[[File:tailoring7.jpg]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:31--&amp;gt;&lt;br /&gt;
Here weight_kg is {if(weight_units == &#039;kg&#039;, weight, weight * .453592)}.  This if() function means that if the subject entered the weight using kilograms, use that value, otherwise multiple the entered value (which was in pounds) by .453592 to convert it to kilograms.  The height_m variable uses a similar approach to compute the person&#039;s height in meters, even if he entered his height in inches.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:32--&amp;gt;&lt;br /&gt;
BMI computes the weight formula as {weight_kg / (height_m * height_m)}.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:33--&amp;gt;&lt;br /&gt;
Lastly, the report conditionally tailors the message for the subject, telling him what he entered. (&amp;quot;You said you are 2 meters tall and weight 70 kg.&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:34--&amp;gt;&lt;br /&gt;
Although not well shown in the above image, weight_status uses nested if() statements to categorize the person as underweight to severely obese.  You can see its equation in the Show Logic View&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:35--&amp;gt;&lt;br /&gt;
[[File:tailoring8.jpg]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:36--&amp;gt;&lt;br /&gt;
From the edit window for this question, you can see two things:&lt;br /&gt;
#Tailoring must surround expressions with Curly Braces&lt;br /&gt;
#Expressions can span multiple lines if, as in this case, you want to make it easier to read the nested conditional logic.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:37--&amp;gt;&lt;br /&gt;
[[File:tailoring9.jpg]]&lt;br /&gt;
&lt;br /&gt;
===Tailored Questions, Answers, and Reports=== &amp;lt;!--T:38--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:39--&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;simplebox&amp;quot;&amp;gt;Note: Dynamic tailoring may not work if answer options are made available in select boxes on the same question page. This results from the fact that tailoring inserts a &amp;lt;nowiki&amp;gt;&amp;lt;span&amp;gt;&amp;lt;/nowiki&amp;gt; tag which is not valid inside select options.&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:40--&amp;gt;&lt;br /&gt;
This example shows the BMI report.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:41--&amp;gt;&lt;br /&gt;
[[File:tailoring10.jpg]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:42--&amp;gt;&lt;br /&gt;
Here is the edit window for the same question.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:43--&amp;gt;&lt;br /&gt;
[[File:tailoring11.jpg]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:44--&amp;gt;&lt;br /&gt;
As you can see, anything in curly braces is treated as an expression, so is syntax-highlighted (color coded) in the prior image.  If you had any typos (such as misspelled or undefined variable names or functions), EM would show an error, such as this, showing that height_unit is an undefined variable name (it is actually height_units), and rnd() is an undefined function (the proper function name is round()).  In both cases, the errors are surrounded by a red box to make it easier to spot and fix them.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:45--&amp;gt;&lt;br /&gt;
[[File:tailoring12.jpg]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:46--&amp;gt;&lt;br /&gt;
You can also see that you can quickly create complex reports, such as a table of entered values or tailored advice.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:47--&amp;gt;&lt;br /&gt;
Please remember that all tailoring must surround expressions with Curly Braces, so that LimeSurvey knows which parts of the question are free text and which should be parsed through Expression Manager.&lt;br /&gt;
&lt;br /&gt;
==Validation== &amp;lt;!--T:48--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:49--&amp;gt;&lt;br /&gt;
EM controls how most of the advanced question options work.  These control aspects like min/max numbers of answers; min/max individual values; min/max sum values; and checking that entered values match specified string patterns.  You continue to enter those advanced question options as usual.  However, now any value in one of those fields is considered an expression, so you can have min/max criteria with complex conditional relationships to other questions.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:50--&amp;gt;&lt;br /&gt;
In all of these cases, since the advanced question option is always considered an expression, you do not use curly braces when specifying it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:51--&amp;gt;&lt;br /&gt;
The [[Expression Manager Sample Surveys|Sample Surveys]] pages shows many working examples of using expressions for validations.&lt;br /&gt;
&lt;br /&gt;
=Introduction= &amp;lt;!--T:52--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:53--&amp;gt;&lt;br /&gt;
LimeSurvey uses the new Expression Manager (EM) module which will let LimeSurvey support more complex branching, assessments, validation, and tailoring.  It will replace how LimeSurvey manages Replacements, Conditions, and Assessments on the back-end.  It will also speed up processing considerably since it eliminates most run-time database reads.  EM was developed by Dr. Thomas White (TMSWhite).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:54--&amp;gt;&lt;br /&gt;
This wiki page is the definitive reference for Expression Manager syntax and functionality.&lt;br /&gt;
&lt;br /&gt;
==Key Definitions== &amp;lt;!--T:55--&amp;gt;&lt;br /&gt;
#&#039;&#039;&#039;Expression&#039;&#039;&#039;:  Anything surrounded by curly braces&lt;br /&gt;
#*As long as there is no white space immediately after the opening brace or before the closing curly brace&lt;br /&gt;
#*The contents of Expressions are evaluted by EM, so they can contain mathematical formulas, functions, and complex string and date processing.&lt;br /&gt;
#&#039;&#039;&#039;Tailoring&#039;&#039;&#039;: Sometimes called &amp;quot;piping&amp;quot;, this is the process of conditionally modifying text&lt;br /&gt;
#*You have access to all &#039;replacement fields&#039;, TOKENs, and INSERTANS values&lt;br /&gt;
#*You also have easier access to questions, answers, and their properties.&lt;br /&gt;
#&#039;&#039;&#039;Relevance&#039;&#039;&#039; Equation:  A new question attribute controlling question visiblity&lt;br /&gt;
#*If there is a relevance equation, then the question is only shown if the relevance evaluates to true.&lt;br /&gt;
#*Internally, all array_filter and array_filter_exclude commands become sub-question-level relevance&lt;br /&gt;
#&#039;&#039;&#039;Equation&#039;&#039;&#039; Question Type:  A new question type that saves calculations or reports to the database&lt;br /&gt;
#*It is like a Boilerplate question, but its contents are saved to the database even if you set &amp;quot;Always Hide this Question&amp;quot;&lt;br /&gt;
#&#039;&#039;&#039;Question Code&#039;&#039;&#039;:  This is the preferred variable name for EM&lt;br /&gt;
#*This can be a descriptive name indicating the purpose of the question, making it easier to read complex logic&lt;br /&gt;
#*Valid question codes should NOT start with a number, so when using the question code to number your questions, simply use &amp;quot;q1&amp;quot;, or &amp;quot;q1a&amp;quot; or &amp;quot;g1q2&amp;quot;.&lt;br /&gt;
#*This is what currently becomes the variable name if you export data to SPSS or R, so if you do statistical analysis, you probably already made this unique.&lt;br /&gt;
&lt;br /&gt;
==Do I have to use EM?== &amp;lt;!--T:56--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:57--&amp;gt;&lt;br /&gt;
The short answer is No (but also yes).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:58--&amp;gt;&lt;br /&gt;
EM is fully backwards-compatible with existing surveys.  So, if you are happy to use Conditions and Assessments in the style that LimeSurvey used in versions &amp;lt;= 1.91+, you can continue to do so.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:59--&amp;gt;&lt;br /&gt;
However, EM completely replaces how LimeSurvey internally deals with Conditions.  Although you can still use the Conditions Editor to create and manage conditions, LimeSurvey 1.92 will convert those to the equivalent Relevance Equations.  As part of the upgrade, LimeSurvey 1.92 will auto-convert all existing Conditions to Relevance Equations.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:60--&amp;gt;&lt;br /&gt;
This should give you the best of both worlds - you can continue using LimeSurvey as you are used to, but will see the Relevance Equation equivalent so you can gradually migrate to Relevance Equations directly whenever you see fit.&lt;br /&gt;
&lt;br /&gt;
==Can I mix use of Conditions and Relevance?== &amp;lt;!--T:61--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:62--&amp;gt;&lt;br /&gt;
Yes. You can use the Conditions editor for some questions and the Relevance editor for others.  Conditions are auto-converted to Relevance when you save the question.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:63--&amp;gt;&lt;br /&gt;
Note, we assume that if you are using the Conditions editor, that you want those Conditions to over-write any manually entered Relevance equation.  So, if you have existing Conditions and want to manually edit the Relevance, please delete the Conditions for that question first.  Specifically, copy the generated relevance equation to a text editor, use the Conditions menu to delete all of the conditions for that question (which will also delete the relevance), then edit the question and paste the generated relevance equation from the text editor back into the relevance field for that question (and save the question).  If there is enough demand for deleting conditions without deleting the generated relevance equation, we could add a bulk conversion process.&lt;br /&gt;
&lt;br /&gt;
==How should I choose between Conditions and Relevance?== &amp;lt;!--T:64--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:65--&amp;gt;&lt;br /&gt;
Here is a list of pros and cons of each style:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:66--&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Style!!Pros!!Cons&lt;br /&gt;
|-&lt;br /&gt;
|Conditions||1. Nice GUI for creating simple conditions &amp;lt;br/&amp;gt;2. GUI well documented and understood by support team||1. Only supports simple comparisons and does not AND/OR conditions well &amp;lt;br/&amp;gt;2. Cascading conditions work erratically &amp;lt;br/&amp;gt;3. Slow - database intensive, so can slow down long surveys &amp;lt;br/&amp;gt;4. Some reported problems with re-loading conditions &amp;lt;br/&amp;gt;5. GUI doesn&#039;t scale well when there are dozens, hundreds, or thousands of questions &amp;lt;br/&amp;gt;6. May be slow to convert paper-based surveys since must use SGQA names &amp;lt;br/&amp;gt;7. Often need a programmer to custom-code logic needed for complex branching&lt;br /&gt;
|-&lt;br /&gt;
|Relevance||1. Supports very complex logic, including 80+ functions and math/string operators &amp;lt;br/&amp;gt;2. Perfect support for cascading logic &amp;lt;br/&amp;gt;3. Fast - no extra database calls, so supports 1000+ question surveys &amp;lt;br/&amp;gt;4. No problems with re-loading logic since does not require SGQA codes &amp;lt;br/&amp;gt;5. Syntax-highlighting scales to 1000+ question surveys &amp;lt;br/&amp;gt;6. Easy and fast to use for groups wanting to computerize existing paper-based suveys.  &amp;lt;br/&amp;gt;7. Easily supports semi-structured interviews and epidemiological surveys without needing a programmers||1. No GUI for simple conditions - use syntax-highlighting instead &amp;lt;br/&amp;gt;2. New, so support teams have not mastered EM yet.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:67--&amp;gt;&lt;br /&gt;
The bottom is that if you are happy with how LimeSurvey 1.91+ works, there is no reason to change what you do.&lt;br /&gt;
&lt;br /&gt;
==What are some other benefits of using EM?== &amp;lt;!--T:68--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:69--&amp;gt;&lt;br /&gt;
Here are some of the other reasons you might want to use EM.&lt;br /&gt;
#Calculations - you can create any calculation you can think of:&lt;br /&gt;
#*You have access to all common mathematical operators and functions&lt;br /&gt;
#*You have access to 70+ mathematical, date, and string processing functions&lt;br /&gt;
#*It is fairly easy for developers to add new functions if users need them&lt;br /&gt;
#Storing Calculations to Database&lt;br /&gt;
#*You can now compute simple and complex calculations and/or scale scores AND have them stored in the database without needing JavaScript.&lt;br /&gt;
#*You use the Equation question type to accomplish this.&lt;br /&gt;
#Assessments&lt;br /&gt;
#*You can now create assessments or scale scores from any question type, not just the subset that used to be supported&lt;br /&gt;
#*You can use Tailoring to show running or total assessment scores anywhere needed - even on the same page&lt;br /&gt;
#*You have more control over the reports generated based upon those assessment scores&lt;br /&gt;
#*You can store assessment scores in the database without needing JavaScript&lt;br /&gt;
#*You can hide assessment scores without needing JavaScript or CSS&lt;br /&gt;
#Replacement Fields&lt;br /&gt;
#*Instead of using {INSERTANS:SGQA}, you can just use the Question Code - this makes it easier to read and validate.&lt;br /&gt;
#*This also avoids the common need to edit questions to change the SGQA code to make everything work.&lt;br /&gt;
#Tailoring - you can conditionally display text based upon other values&lt;br /&gt;
#*Use the appropriate title for a subject, like (e.g. &amp;quot;Hello &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;Mr./Mrs.] Smith&amp;quot;)&lt;br /&gt;
#*Output gramatically correct sentences based when singular/plural matter:  (e.g. &amp;quot;You have 1 child&amp;quot; vs. &amp;quot;You have 2 children&amp;quot;)&lt;br /&gt;
#*Appropriately conjugate verbs and decline nouns based upon subject&#039;s gender and plurality.&lt;br /&gt;
#New Variable Attributes - you can access the following to do your tailoring:&lt;br /&gt;
#* (no suffix) -  an alias for qcode.code&lt;br /&gt;
#*.code - the selected response code for the question if it is relevant (otherwise blank), or the text value if it is not a coded question&lt;br /&gt;
#*.NAOK - same as .code, but can be part of calculations or lists even if irrelevant&lt;br /&gt;
#*.value - the assessment value for the question if it is relevant (otherwise blank), or the text value if it is not a coded question&lt;br /&gt;
#*.valueNAOK - same as .value, but can be part of calculations or lists even if irrelevant&lt;br /&gt;
#*.shown - the answer as displayed to the user (this is what {INSERTANS:xxx}  does)&lt;br /&gt;
#*.qid - the question ID&lt;br /&gt;
#*.gid - the group ID&lt;br /&gt;
#*.sgqa - the SGQA value for the question&lt;br /&gt;
#*.jsName - the correct javascript variable name for the question, regardless whether defined on this page or another&lt;br /&gt;
#*.qseq - the question sequence (starting from 0)&lt;br /&gt;
#*.gseq - the group sequence (starting from 0)&lt;br /&gt;
#*.mandatory - whether the question is mandatory (Y/N)&lt;br /&gt;
#*.question - the text of the question&lt;br /&gt;
#*.relevance - the relevance equation for the question&lt;br /&gt;
#*.grelevance - the relevance equation for the group&lt;br /&gt;
#*.relevanceStatus - whether or not the question is currently relevant (1 if true, 0 if false)&lt;br /&gt;
#*.type - the question type (the one character code)&lt;br /&gt;
#Dynamic On-Page Changes&lt;br /&gt;
#*All Relevance, Calculation, and Tailoring works dynamically on a page - so changes in values instantly update the page&lt;br /&gt;
#*So, you have questions dynamically appear/disappear based upon whether they are relevant&lt;br /&gt;
#*Questions are also dynamically tailored based upon responses on the page, so you can see running totals, tailored sentences and customized reports.&lt;br /&gt;
#New Data Entry Screen&lt;br /&gt;
#*In addition to using the current data-entry system, you can just use Survey-All-In-One.&lt;br /&gt;
#*This supports the on-page relevance and tailoring, so data entry clerks can quickly tab through and they will only have to enter the relevant responses&lt;br /&gt;
#*This can be critical if your data entry person needs to see the tailoring, which is also dynamic.&lt;br /&gt;
#Eliminates the need for most custom JavaScript&lt;br /&gt;
#*EM easily supports complicated computations, scoring, tailoring and conditional logic.&lt;br /&gt;
#*Some things will still need JavaScript (like custom layouts and conditionally hiding question sub-elements), but your JavaScript can use the EM functions so that you can access questions by their Qcode instead of SGQA, and access any of the question properties listed above.&lt;br /&gt;
&lt;br /&gt;
==What are some other helpful new features enabled by EM?== &amp;lt;!--T:70--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:71--&amp;gt;&lt;br /&gt;
Regardless of whether you continue to use the Conditions Editor or manually compose Relevance Equations, you get these additional benefits:&lt;br /&gt;
#You can create more complex validation criteria&lt;br /&gt;
#*All of the advanced question attribute (like max_answers, min_num_value_n, max_num_value) can use Expressions.  So, you min/max criteria can be easily adjusted based upon prior responses, even if they are on the same page.&lt;br /&gt;
#*EM also handles all regular-expression-based validation, so you can robustly combine preg and equation-based question attributes.&lt;br /&gt;
#Easy Re-ordering (or deleting) of Questions and Groups&lt;br /&gt;
#*Prior to version 1.92, you could not re-order questions or groups if LimeSurvey thought that such-re-ordering could break conditions in which they were used.  Similarly, you could not delete questions if any other questions depended upon them.&lt;br /&gt;
#*With EM&#039;s syntax highlighting, it is easy to see and validate whether you try to use questions before they are declared.  So, we now let you re-order or delete questions and groups whenever you like.  EM will update all of the syntax highlighting to show you potential errors.&lt;br /&gt;
#*The re-order questions view has been enhanced to help with such review.  It now shows the question&#039;s relevance equation and tailoring, so you can immediately see whether any variables become pink (meaning they are used before being declared).&lt;br /&gt;
#The Question/Group Navigation Index is always available and accurate&lt;br /&gt;
#*Prior to version 1.92, these indexes were not available if there were complex conditions&lt;br /&gt;
#*With EM, we can guarantee that they are accurate.&lt;br /&gt;
#*Subjects can even jump back, to a prior question, change the answer, then jump forward (or submit)&lt;br /&gt;
#**When jumping forwards, EM will re-validate all of the intervening questions/groups.&lt;br /&gt;
#**If any questions become irrelevant, they will be NULLed in the database so that your data is internally consistent&lt;br /&gt;
#**If any questions become relevant or newly fail mandatory or validation rules, EM will stop on that page and force the user to answer those questions before jumping to their final destination.&lt;br /&gt;
#Auto-conversion of Conditions to Relevance&lt;br /&gt;
#*When you upgrade your database, all existing surveys that have conditions will have relevance equations generated for them&lt;br /&gt;
#*Whenever you import a survey, relevance equations will be created as needed&lt;br /&gt;
#*Whenever you add, delete, or modify conditions, EM will generate the appropriate relevance equation.&lt;br /&gt;
#Convenient Syntax Highlighting&lt;br /&gt;
#*When EM shows the relevance equation, it will show the Qcode, even if you entered an SGQA code, as we assume this will be easier to read.&lt;br /&gt;
#*All variables are color coded to show whether they were declared before or after the current question (or before or after the current group).  This lets you quickly detect and fix cases where you try to use variables for relevance (including array_filter), tailoring, or validation equations prior to declaring them.&lt;br /&gt;
#*In addition, if you hover your mouse over the color-coded variable, you will see the most important metadata about that question.   This includes the Group Sequence #, Question Sequence #, Qcode, Text of the question, and all available answer choices (if it is a question type with enumerated answer choices).&lt;br /&gt;
#**The list of answer choices uses this syntax:  &#039;answers&#039;:{key:val, ... }.&lt;br /&gt;
#**&#039;&#039;key&#039;&#039; has the syntax &#039;&#039;&#039;&#039;scale~code&#039;&#039;&#039;&#039; where &#039;&#039;scale&#039;&#039; is the answer scale (e.g. for dual scale), and &#039;&#039;code&#039;&#039; is the answer code.&lt;br /&gt;
#**&#039;&#039;val&#039;&#039; has the syntax &#039;&#039;&#039;&#039;value~shown&#039;&#039;&#039;&#039; where &#039;&#039;value&#039;&#039; is the assessment value (if using assessments, otherwise &#039;&#039;code&#039;&#039;)(e.g. Qcode.value), and &#039;&#039;shown&#039;&#039; is the display value as seen by the subject (e.g. Qcode.shown)&lt;br /&gt;
#**This means that many surveys can use calculations without needing assessment mode.  If you have enumerated answer options  that are unique, non-decimal, and non-negative, you can simply do calculations on the Qcode.code values.&lt;br /&gt;
#Easy review of entire survey logic and content&lt;br /&gt;
#*There is a new Show Survey Logic feature that lets you see everything about the survey (or group or question) on a single page.&lt;br /&gt;
#*It shows the Group, Question, Sub-Question, and Answer-level details for the selected scope (survey vs. group vs. question)&lt;br /&gt;
#*It also shows the relevance, sub-question-level relevance (for array_filter and array_filter_exclude), and generated validation equation (for preg and any validation rules like min/max sum/number of values), and all non-blank question attributes.&lt;br /&gt;
#*Everything is syntax-highlighted so that you can see potential syntax errors (like unbalanced parentheses or use of variables before they were declared)&lt;br /&gt;
#*The syntax-highligting supports rapid navigation and editing of the survey.&lt;br /&gt;
#**If you click on a variable name, it opens a browser window (or tab) that shows you that question and lets you edit it.&lt;br /&gt;
#**If you click on a group name, it opens a browser window (or tab) showing the group-reorder view so that you can easily move questions around.&lt;br /&gt;
#**All of the question attributes are also syntax highlighted.  This lets you set and see expressions within advanced question options (like basing the max/min number/sum of values on an expression)&lt;br /&gt;
#*The EM author used similar view (a little cleaner) to let his collaborating Epidemiologists and Institutional Review Board validate and authorize surveys with thousands of questions in highly branched and tailored structured interviews&lt;br /&gt;
&lt;br /&gt;
==How Backwards Compatible is EM with 1.91+?== &amp;lt;!--T:72--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:73--&amp;gt;&lt;br /&gt;
LimeSurvey 1.92 is fully backwards-compatible with 1.91+ with one exception/caveat:  1.92 handles less-than / greater-than comparisons against empty values differently than 1.91+.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:74--&amp;gt;&lt;br /&gt;
One of the LimeSurvey demo surveys uses a set of conditions that translates to this relevance equation:  {(age &amp;lt; 16) or (age == 20) or ... or (age == 80)}. In LimeSurvey 1.91+, (age &amp;lt; 16) is FALSE when there is no answer (the value is blank).  However, in LimeSurey 1.92, (age &amp;lt; 16) is TRUE when there is no answer, since both PHP and JavaScript treat blank as 0 in mathematical comparisons.  Thus, 1.91+ would hide that question when age was unanswered, but 1.92 would show it.  We went to great pains to prevent this, but since we needed to have the Expressions generate identical results in PHP and JavaScript, there was no way to make 1.92 treat &amp;quot;&amp;quot; &amp;lt; 16 as FALSE.  Fortunately, there is an easy work-around for this.  If you want (age &amp;lt; 16) to be FALSE, then use this expression instead: {(!is_empty(age) and age &amp;lt; 16)}.  You can use the new [[Show Logic File|Survey Logic File]] view to quickly identify and fix any such comparisons in your survey.&lt;br /&gt;
&lt;br /&gt;
=Getting Started= &amp;lt;!--T:75--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:76--&amp;gt;&lt;br /&gt;
The best way to get started with EM is to:&lt;br /&gt;
*Install the latest stable version from http://www.limesurvey.org/en/download &lt;br /&gt;
*Import and explore the [[Expression Manager Sample Surveys|sample surveys]].&lt;br /&gt;
*Explore the [[Expression Manager HowTos|use cases and HowTos]] and [[Expression Manager Examples|step-by-step examples]].&lt;br /&gt;
*Explore the EM documentation (this page)&lt;br /&gt;
*Examine the built-in EM test suite&lt;br /&gt;
**From any survey, under tools, select the EM option&lt;br /&gt;
**Available Functions lists the 70+ functions and syntax&lt;br /&gt;
**Unit Tests of Isolated Expressions&lt;br /&gt;
***shows examples of using all EM functions and operators, and the PHP and JavaScript results&lt;br /&gt;
***note there are few functions that generate different results in the PHP and JavaScript versions, so this page lets you plan your EM logic accordingly.&lt;br /&gt;
&lt;br /&gt;
=What Functionality does Expression Manager Extend/Replace? (LimeSurvey &amp;lt;= 1.91+)= &amp;lt;!--T:77--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Conditions =&amp;gt; Relevance== &amp;lt;!--T:78--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:79--&amp;gt;&lt;br /&gt;
Conditions controlled which  questions are visible.  The general syntax was &#039;&#039;SGQA operator Value&#039;&#039;, like &#039;&#039;111X2X3 == &amp;quot;Y&amp;quot;&#039;&#039;.  Conditions could be ANDed or ORed together, but mixing ANDs and ORs was difficult.  The conditions themselves were stored in a separate table, and large portion of LimeSurvey&#039;s code was devoted to managing Conditions.  Because of extensive database access, processing large numbers of conditions could cause noticable performance problems.  Furthermore, once you had conditions assigned to questions or groups, you were often not allowed to re-order or delete them.&lt;br /&gt;
&lt;br /&gt;
==Assessments =&amp;gt; Equations and  Micro-Tailoring== &amp;lt;!--T:80--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:81--&amp;gt;&lt;br /&gt;
Assessments let users create scale scores from a collection of questions.  However, they could not dynamically change on the current page, and their values were not stored to the database.&lt;br /&gt;
&lt;br /&gt;
==Replacements =&amp;gt; Micro-Tailoring== &amp;lt;!--T:82--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:83--&amp;gt;&lt;br /&gt;
Users could tailor some messages and questions based  upon prior responses.  For example, a question might be, &#039;&#039;{TOKEN:FIRSTNAME}, you said {INSERTANS:111X3X4} was your favorite sport&#039;&#039;.  However, it was not possible to do conditional tailoring (like say &amp;quot;Mr.&amp;quot; or &amp;quot;Mrs.&amp;quot; depending upon the person&#039;s gender), or conjugate verbs or decline nouns without fancy JavaScript.  Authors could implement surveys that seemed to tailor questions, but it required separate questions for each permutation, and complex conditions to decide which questions to display.&lt;br /&gt;
&lt;br /&gt;
==Validation== &amp;lt;!--T:84--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:85--&amp;gt;&lt;br /&gt;
Question could be validated with Regular expressions, or minimum/maximum values, or let an SGQA response serve as the minimum or maximum value.  However, validations could not be based upon calculations of other variables without fancy JavaScript.&lt;br /&gt;
&lt;br /&gt;
==Equations== &amp;lt;!--T:86--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:87--&amp;gt;&lt;br /&gt;
Equations were not supported without fancy JavaScript.&lt;br /&gt;
&lt;br /&gt;
==Equation Question Type== &amp;lt;!--T:88--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:89--&amp;gt;&lt;br /&gt;
Equations could not be saved to the database (e.g. the final score for an assessment) without fancy JavaScript.&lt;br /&gt;
&lt;br /&gt;
=How Will Expression Manager Replace/Extend That Functionality?= &amp;lt;!--T:90--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:91--&amp;gt;&lt;br /&gt;
The Expression Manager is a new core module within LimeSurvey that makes it much easier to support the type of complex functionality that used to require custom JavaScript.  It is also replacing the way LimeSurvey currently manages Conditions and Assessments.&lt;br /&gt;
&lt;br /&gt;
==New Terminology When Referring to Expression Manager (EM)== &amp;lt;!--T:92--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:93--&amp;gt;&lt;br /&gt;
EM &amp;quot;thinks&amp;quot; of its functionality in the following terms:&lt;br /&gt;
*&#039;&#039;&#039;Relevance-based Branching&#039;&#039;&#039; - if a question is relevant, then ask it, otherwise don&#039;t (e.g. make it invisible, and mark it as NULL in the database).  There is a new Relevance field for all Question types, and also for each Group (so you can apply a set of conditions to an entire group without having to copy the same condition to each question, and/or combine group and question-level conditional logic).&lt;br /&gt;
*&#039;&#039;&#039;Tailoring&#039;&#039;&#039; - Once you know which questions should be asked, tailoring (sometimes called &#039;&#039;piping&#039;&#039;) specifies how the question should be asked. This lets you support not only simple subsitution (like {TOKEN:FIRSTNAME}), but also conjugation of verbs and declination of nouns based upon the gender or number of your subjects.  It also lets you change the message you deliver to a subject based upon whether they answered (or how they answered) other questions.&lt;br /&gt;
*&#039;&#039;&#039;Equations&#039;&#039;&#039; - EM adds a new question type called Equation which stores the result of an Expression.  These equations results are computed and written to the database, even if you hide them on the page.  Thus, they are useful for hidden scoring calculations, navigation based upon complex equations, assessments, and reports that should be generated and easily available within the database.&lt;br /&gt;
&lt;br /&gt;
===Relevance and Cascading Relevance=== &amp;lt;!--T:94--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:95--&amp;gt;&lt;br /&gt;
Every question type now has a Relevance option which controls whether the question is displayed.  EM processes each of the Relevance Equations in the order they should appear in the survey.  If the expression is true (or missing - to support legacy surveys), the question will be displayed. If it is not relevant, then the question will be hidden, and the value will be NULLed in the database.  If there are no relevant questions in a group, the entire group will be skipped.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:96--&amp;gt;&lt;br /&gt;
Moreover, if any of the variables within an expression is irrelevant, then the expression always evaluates to false.  This enables Cascading Relevance so that you do not have to write very long Relevance equations for each question.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:97--&amp;gt;&lt;br /&gt;
Say you have 5 questions Q1-Q5, and you only want to show Q2 if Q1 was answered, and Q3 if Q2 was answered, etc.  The relevance equations might be:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:98--&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Question Code!!Relevance!!Question&lt;br /&gt;
|-&lt;br /&gt;
|Q1||1||What is your name?&lt;br /&gt;
|-&lt;br /&gt;
|Q2||Q1||{Q1}, how old are you?&lt;br /&gt;
|-&lt;br /&gt;
|Q3||Q2||So, you are {Q2} years old.  Are you married?&lt;br /&gt;
|-&lt;br /&gt;
|Q4||Q3 == &amp;quot;Y&amp;quot;||{Q1}, how long have you been married?&lt;br /&gt;
|-&lt;br /&gt;
|Q5||Q4||How many children do you have, {Q1}?&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:99--&amp;gt;&lt;br /&gt;
The relevance calculations also work in JavaScript - so you could put all the above questions on one page and it would still work as expected.  In fact, EM totally replaces how EM processes Survey vs. Group vs. Question-at-a-time survey formats.  They now all use the exactly same navigation engine so they work identically regardless of survey style.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:100--&amp;gt;&lt;br /&gt;
As long as you are on the same page, any data you entered will still be there, just hidden.  So, if you enter some information, then choose an option that makes them irrelevant, then make them relevant again, your answers will still be available.  However, as soon as you move to a different page, all irrelevant responses will be lost to integrity of the dataset.&lt;br /&gt;
&lt;br /&gt;
===Group-Level Relevance=== &amp;lt;!--T:101--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:102--&amp;gt;&lt;br /&gt;
Expression Manager also supports group-level relevance.  This makes it easier to implement looping.   Say you want to collect information about up to 10 entities (such a products or people in a household), where you first determine how many entities need follow-up (such as by asking how many people live in a household, or having people check which products they like from a long list).  After knowning how many entities need follow-up, you can use Group-level relevance like {count &amp;gt;= 1}, {count &amp;gt;=2}, ... {count &amp;gt;= 10} for each of the 10 groups of follow-up questions.  Within each group, you can have question-level conditional logic (e.g. gender or age-specific follow-up questions for each subject).  The question and group-level relevance equations are ANDed together to determine which should be shown.&lt;br /&gt;
&lt;br /&gt;
===Tailoring / Piping=== &amp;lt;!--T:103--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:104--&amp;gt;&lt;br /&gt;
Anything within curly braces is now treated as an Expression (with one exception described below).  Expressions have acccess to all of the LimeReplacementFields, all of the variables (via several aliases), all typical equation operators (mathematical, logical, and comparison), and dozens of functions (that even work dynamically on the client-side).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:105--&amp;gt;&lt;br /&gt;
Using these equations, you can do things such as:&lt;br /&gt;
#Conditionally show tailored messages to the respondants based upon prior responses&lt;br /&gt;
#Create Assessments and show Assessment results (or conditionally branch or show messages) based upon those results, all without using the Assessments module itself&lt;br /&gt;
#Conjugate verbs and decline nouns within questions, answers, and reports.&lt;br /&gt;
#Show summaries of responses before the &amp;quot;Show your answers&amp;quot; page at the end of the survey&lt;br /&gt;
&lt;br /&gt;
===Equations=== &amp;lt;!--T:106--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:107--&amp;gt;&lt;br /&gt;
There is a new question type called  Equation.  It is like a Boilerplate questions, except that it stores the value of what is displayed in the database.  So, if the Equation Question text contains an Assessment computation, that value would be stored in the database in a variable that can be displayed within public or private statistics.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:108--&amp;gt;&lt;br /&gt;
This solves a common request for storing Assessment scores within the database&lt;br /&gt;
&lt;br /&gt;
==Syntax== &amp;lt;!--T:109--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:110--&amp;gt;&lt;br /&gt;
Anything contained within curly braces is now considered an Expression (with one exception:  there must be no leading or trailing whitespace - this is needed to ensure the Expression Manager does not try to process embedded JavaScript).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:111--&amp;gt;&lt;br /&gt;
Note, it is OK for expressions to span multiple lines, as long as there is no whitespace after the opening  curly brace or before the closing curly brace.  This is especially helpful for nested if() statements like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:112--&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;{if(is_empty(PFTotals),&lt;br /&gt;
 &#039;&#039;,&lt;br /&gt;
 if(PFTotals &amp;gt;= -5 &amp;amp;&amp;amp; PFTotals &amp;lt;= -4,&lt;br /&gt;
   &#039;Very Soft&#039;,&lt;br /&gt;
   if(PFTotals &amp;gt;= -3 &amp;amp;&amp;amp; PFTotals &amp;lt;= -2,&lt;br /&gt;
     &#039;Soft&#039;,&lt;br /&gt;
     if(PFTotals == -1,&lt;br /&gt;
       &#039;Somewhat Soft&#039;,&lt;br /&gt;
       if(PFTotals == 0,&lt;br /&gt;
         &#039;Moderate&#039;,&lt;br /&gt;
         if(PFTotals == 1,&lt;br /&gt;
           &#039;Somewhat Hard&#039;,&lt;br /&gt;
           if(PFTotals &amp;gt;= 2 &amp;amp;&amp;amp; PFTotals &amp;lt;= 3,&lt;br /&gt;
             &#039;Hard&#039;,&lt;br /&gt;
             if(PFTotals &amp;gt;= 4 &amp;amp;&amp;amp; PFTotals &amp;lt;= 5,&lt;br /&gt;
               &#039;Very Hard&#039;,&lt;br /&gt;
               &#039;&#039;&lt;br /&gt;
             )&lt;br /&gt;
           )&lt;br /&gt;
         )&lt;br /&gt;
       )&lt;br /&gt;
     )&lt;br /&gt;
   )&lt;br /&gt;
 )&lt;br /&gt;
)}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:138--&amp;gt;&lt;br /&gt;
&amp;lt;div id=&amp;quot;EMsyntax&amp;quot;&amp;gt;Expression Manager supports the following syntax:&amp;lt;/div&amp;gt;&lt;br /&gt;
*All standard mathematical operators (e.g. +,-,*,/,!)&lt;br /&gt;
*All standard comparison operators (e.g. &amp;lt;,&amp;lt;=,==,!=,&amp;gt;,&amp;gt;=, plus these equivalents:  lt,le,eq,ne,gt,ge)&lt;br /&gt;
*Parentheses (so you can group sub-expressions)&lt;br /&gt;
*Conditional operators (e.g. &amp;amp;&amp;amp;,| | and these equivalents: and,or)&lt;br /&gt;
*Single and double-quoted strings (which can each embed strings with the other quote type)&lt;br /&gt;
*Comma operator (so can have a list of expressions and just return the final result)&lt;br /&gt;
*Assignment operator (=)&lt;br /&gt;
*Pre-defined variables (to refer to questions, question attributes, and responses) - e.g. all of the SGQA codes&lt;br /&gt;
*Pre-defined functions (there are already 70+, and it is easy to add more)&lt;br /&gt;
&lt;br /&gt;
=== Operators === &amp;lt;!--T:211--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:139--&amp;gt;&lt;br /&gt;
EM syntax follows normal operator precedence:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:140--&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Level!!Operator(s)!!Description&lt;br /&gt;
|-&lt;br /&gt;
|1||()||parentheses for grouping or calling functions&lt;br /&gt;
|-&lt;br /&gt;
|2||! - +||unary operators: not, negation, unary-plus&lt;br /&gt;
|-&lt;br /&gt;
|3||* /||times, divide&lt;br /&gt;
|-&lt;br /&gt;
|4||+ -||plus, minus&lt;br /&gt;
|-&lt;br /&gt;
|5||&amp;lt; &amp;lt;= &amp;gt; &amp;gt;= lt le gt ge||relative comparisons&lt;br /&gt;
|-&lt;br /&gt;
|6||== != eq ne||equality comparisons&lt;br /&gt;
|-&lt;br /&gt;
|7||and||logical AND&lt;br /&gt;
|-&lt;br /&gt;
|8||or||logical OR&lt;br /&gt;
|-&lt;br /&gt;
|9||=||assignment operator&lt;br /&gt;
|-&lt;br /&gt;
|10||,||comma operator&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:141--&amp;gt;&lt;br /&gt;
Note, for consistency between JavaScript and PHP, the plus operator (+) does addition if both operands are numeric, but does concatenation if both parts are non-numeric strings.  However, we recommend using the join() function for concatenation, as that makes your intent more clear, and avoids unexpected results if you were expecting strings but got numbers instead (or vice versa).&lt;br /&gt;
&lt;br /&gt;
===Caution about using Assignment Operator (=)=== &amp;lt;!--T:142--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:143--&amp;gt;&lt;br /&gt;
Note, you should avoid using the assignment operators unless absolutely necessary, since they may cause unexpected side-effects.  For example, if you change the value of a previous response, the cascading relevance and validation logic between that question and the current question is not re-computed, so you could end up with internally inconsistent data (e.g. questions that stay answered but should have been NULLed, or questions that are skipped but should have been answered).  In general, if you want to assign a value to a variable, you should create an Equation question type, and use an expression to set its value.  However, there are some rare times that people really need this operator, so we made it available.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:144--&amp;gt;&lt;br /&gt;
To help caution you about this operator, it is shown in red font within the syntax equations (so that you don&#039;t confuse it with &amp;quot;==&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
===Using Assignment Operator=== &amp;lt;!--T:145--&amp;gt;&lt;br /&gt;
The main reasons you may want to use assignment are:&lt;br /&gt;
*You need to set the default value for a question that does not accept defaults via equation (such as list radio, where the user interface lets you pick one of the answer options, but does not let you enter an equation).  However, be careful, as LimeSurvey will not be able to validate that your equation generates one of the allowable answers for that question.&lt;br /&gt;
*You need to forcibly change the response to a previous question based upon a later response&lt;br /&gt;
* etc...&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:212--&amp;gt;&lt;br /&gt;
You can use all expression manager system for this purpose. It&#039;s better to use an [[Question_type_-_Equation|Equation question]] type to this purpose.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:213--&amp;gt;&lt;br /&gt;
Some example:&lt;br /&gt;
* Set answer to a short text question in lowercase : &amp;lt;code&amp;gt;{QCODE=strtolower(QCODE.NAOK)}&amp;lt;/code&amp;gt;&lt;br /&gt;
* Set a default answer to an array question type at start of a survey : &amp;lt;code&amp;gt;{Q1_SQ1=(is_empty(Q1_SQ1.NAOK),&amp;quot;A99&amp;quot;,Q1_SQ1.NAOK)}&amp;lt;/code&amp;gt;&lt;br /&gt;
* Set a default answer to an array texts question type at start of a survey : &amp;lt;code&amp;gt;{Q1_SQY1_SQX1 = (is_empty(Q1_SQY1_SQX1.NAOK),&amp;quot;Inserted answer&amp;quot;, Q1_SQY1_SQX1.NAOK)}&amp;lt;/code&amp;gt;&lt;br /&gt;
* Set an answer with condition : &amp;lt;code&amp;gt;{QCODE=if(YesNo=&amp;quot;Y&amp;quot;,&amp;quot;A1&amp;quot;,&amp;quot;&amp;quot;)}&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== XSS security == &amp;lt;!--T:214--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:215--&amp;gt;&lt;br /&gt;
With XSS enable, some expression manager system can not be used : &lt;br /&gt;
* starting a HTML tag in expression but ending in another expression&lt;br /&gt;
* use a complex expression in URL. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:216--&amp;gt;&lt;br /&gt;
Example and workaround&lt;br /&gt;
* &amp;lt;code&amp;gt;{if( 1 ,&amp;quot;&amp;amp;lt;strong&amp;amp;gt;&amp;quot;,&amp;quot;&amp;quot;)}information{if( 1 ,&amp;quot;&amp;amp;lt;/strong&amp;amp;gt;&amp;quot;,&amp;quot;&amp;quot;)}&amp;lt;/code&amp;gt; is broken with XSS security, here you can use &amp;lt;code&amp;gt;{if(1,&amp;quot;&amp;lt;strong&amp;amp;gt;information&amp;amp;lt;/strong&amp;amp;gt;&amp;quot;,&amp;quot;information&amp;quot;)}&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;&amp;amp;lt;a href=&amp;quot;/script.php?value={if(QCODE == &amp;quot;Y&amp;quot;,&amp;quot;yes&amp;quot;,&amp;quot;no&amp;quot;)}&amp;quot;&amp;amp;gt;next&amp;amp;lt;/a&amp;amp;gt;&amp;lt;/code&amp;gt;, here you can use an equation question because using a complete question code is OK : &amp;lt;code&amp;gt;&amp;amp;lt;a href=&amp;quot;/script.php?value={EQUATION.NAOK}&amp;quot;&amp;amp;gt;next&amp;amp;lt;/a&amp;amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Access to Variables== &amp;lt;!--T:146--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:147--&amp;gt;&lt;br /&gt;
Expression Manager provides read-only access to whichever variables we might need.  For backwards compatibility, it provides access to the following:&lt;br /&gt;
*TOKEN:xxx - the value of a TOKEN (e.g. TOKEN:FIRSTNAME, TOKEN:ATTRIBUTE_5) (Only for NOT anonymous survey).&lt;br /&gt;
*[[Adding a question#Information_from_previous_answers|INSERTANS:SGQA]] - the display value of an answer (e.g. &amp;quot;Yes&amp;quot;). For Expression Manager it&#039;s the same that using {QCODE.shown}.&lt;br /&gt;
*All [[The_template_editor#Keywords|{XXX} values used by templates]].&lt;br /&gt;
*In question text, you can use {QID} replaced by the question id and {SGQ} replaced by the SGQA of the question&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:148--&amp;gt;&lt;br /&gt;
In addition, Expression Manager lets you refer to variables by the Question Code (the &#039;title&#039; column in the questions table within the database).  This is also the variable label used when you export your data to SPSS, R, or SAS.  For example, if you have questions about name, age, and gender, you could call those variables &#039;&#039;name&#039;&#039;, &#039;&#039;age&#039;&#039;, and &#039;&#039;gender&#039;&#039; instead of &#039;&#039;12345X13X22&#039;&#039;, &#039;&#039;12345X13X23&#039;&#039;, and  &#039;&#039;12345X13X24&#039;&#039;.  This makes equations easier for everyone to read and validate the logic, plus makes it possible to shuffle questions around without having to keep track of group or question numbers.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:210--&amp;gt;&lt;br /&gt;
&amp;lt;div class=&#039;simplebox&#039;&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Important:&#039;&#039;&#039; It is only safe to refer to variables that occur in preceding pages or questions.&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:149--&amp;gt;&lt;br /&gt;
Furthermore, Expression Manager lets you access many properties of the Question:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:150--&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Syntax!!Meaning!!Example!!Example Result&lt;br /&gt;
|-&lt;br /&gt;
|Qcode||an alias for Qcode.code||{implode(&#039;,&#039;,name,gender)}||&#039;Tom&#039;,&#039;M&#039;&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.code||the selected response code for the question if it is relevant (otherwise blank), or the text value if it is not a coded question||{implode(&#039;,&#039;,name.code,gender.code)}||&#039;Tom&#039;,&#039;M&#039;&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.NAOK||same as Qcode - see discussion of NAOK||{gender.NAOK}||&#039;M&#039;&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.value||the assessment value for the question if it is relevant (otherwise blank), or the text value if it is not a coded question||{gender.value}||&#039;1&#039;&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.valueNAOK||same as Qcode.value - see discussion about NAOK||{gender.valueNAOK}||&#039;1&#039;&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.shown||the dispay value for the question||{implode(&#039;,&#039;,name.shown,gender.shown)}||&#039;Tom&#039;,&#039;Male&#039;&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.question||the text of the question||{gender.question}||&#039;What is your gender?&#039;&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.mandatory||whether the question is mandatory (Y/N)||{gender.mandatory}||&#039;N&#039;&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.qid||the internal question number (not the sequential number)||{gender.qid}||337&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.type||the question type||{gender.type}||&#039;G&#039;&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.jsName||the correct javascript name for the question, regardless whether declared on or off this page||{gender.jsName}||&#039;java1827X3X337&#039;&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.gid||the internal group number (not the sequential number)||{gender.gid}||3&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.qseq||the sequential number of the question, starting from 0||{gender.qseq}||5&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.gseq||the sequential number of the group, starting from 0||{gender.gseq}||1&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.relevanceStatus||whether the question is currently relevant (0 or 1)||{gender.relevanceStatus}||1&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.relevance||the question-level relevance equation||{gender.relevance}||&#039;!is_empty(name)&#039;&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.grelevance||the  group-level relevance equation||{gender.grelevance}||&#039;num_children &amp;gt;= 5&#039;&lt;br /&gt;
|-&lt;br /&gt;
|Qcode.sgqa||the SGQA value for this question||{gender.sgqa}||&#039;1827X3X337&#039;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== HTML editor issue=== &amp;lt;!--T:151--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:217--&amp;gt;&lt;br /&gt;
{{Alert|This issue is fixed after 2.05 build 140803}} &lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:152--&amp;gt;&lt;br /&gt;
If you use HTML editor, some characters are replaced by HTML entities.&lt;br /&gt;
* &amp;amp; by &amp;amp;amp;amp;&lt;br /&gt;
* &amp;lt; by &amp;amp;amp;lt;&lt;br /&gt;
* &amp;gt; by &amp;amp;amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:209--&amp;gt;&lt;br /&gt;
If you use HTML editor you need to use :&lt;br /&gt;
* and for &amp;amp;&lt;br /&gt;
* lt for &amp;lt;&lt;br /&gt;
* le for &amp;lt;=&lt;br /&gt;
* gt for &amp;gt;&lt;br /&gt;
* ge for &amp;gt;=&lt;br /&gt;
&lt;br /&gt;
==Qcode Variable Naming== &amp;lt;!--T:153--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:154--&amp;gt;&lt;br /&gt;
Here are the details of how to construct a Qcode (and access some properties) by question type.  In general, Qcodes are constructed as:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:155--&amp;gt;&lt;br /&gt;
  QuestionCode . &#039;_&#039; . SubQuestionID . &#039;_&#039; . ScaleId&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:208--&amp;gt;&lt;br /&gt;
For comment and other, question code are QuestionCode_comment and QuestionCode_other&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:156--&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Type!!Description!!Code!!SubQs!!Answer Options!!Scales!!Answer Code!!Answer Shown!!Relevance&lt;br /&gt;
|-&lt;br /&gt;
|5||5 Point Choice Radio-Buttons||Q1|| ||1-5|| ||{Q1}||{Q1.shown}||{Q1==3}&lt;br /&gt;
|-&lt;br /&gt;
|B||Array (10 Point Choice) Radio-Buttons||Q2||L1-L6||1-10|| ||{Q2_L2}||{Q2_L2.shown}||{Q2_L2==7}&lt;br /&gt;
|-&lt;br /&gt;
|A||Array (5 Point Choice) Radio-Buttons||Q3||1-5||1-5|| ||{Q3_1}||{Q3_1.shown}||{Q3_1&amp;gt;=3}&lt;br /&gt;
|-&lt;br /&gt;
|1||Array (Flexible Labels) Dual Scale||Q4||sq1-sq5||0:a1-a3||1:b1-b3||{Q4_sq1_0}||{Q4_sq1_1.shown}||{Q4_sq1_1==&#039;b2&#039;}&lt;br /&gt;
|-&lt;br /&gt;
|H||Array (Flexible) - Column Format||Q5||1-5||s,m,t|| ||{Q5_1}||{Q5_1.shown}||{Q5_1==&#039;s&#039;}&lt;br /&gt;
|-&lt;br /&gt;
|F||Array (Flexible) - Row Format||Q6||F1-F5||1-5|| ||{Q6_F3}||{Q6_F3.shown}||{Q6_F3==4}&lt;br /&gt;
|-&lt;br /&gt;
|E||Array (Increase/Same/Decrease) Radio-Buttons||Q7||1-7||I,S,D|| ||{Q7_4}||{Q7_4.shown}||{Q7_4==&#039;D&#039;}&lt;br /&gt;
|-&lt;br /&gt;
|:||Array (Multi Flexi) 1 To 10||Q8||ls1,todo,ls2||min,max,avg|| ||{Q8_ls1_max}||{Q8_ls2_avg.shown}||{Q8_ls2_min==7}&lt;br /&gt;
|-&lt;br /&gt;
|;||Array (Multi Flexi) Text||Q9||hp,st,sw||1st,2nd,3rd|| ||{Q9_hp_3rd}||{Q9_hp_3rd.shown}||{Q9_hp_3rd==&#039;Peter&#039;}&lt;br /&gt;
|-&lt;br /&gt;
|C||Array (Yes/Uncertain/No) Radio-Buttons||Q10||1-5||Y,N,U|| ||{Q10_1}||{Q10_1.shown}||{Q10_3==&#039;Y&#039;}&lt;br /&gt;
|-&lt;br /&gt;
|X||Boilerplate Question||Q11|| || || || ||{Q11.shown}||&lt;br /&gt;
|-&lt;br /&gt;
|D||Date||Q12|| || || ||{Q12}||{Q12.shown}||&lt;br /&gt;
|-&lt;br /&gt;
|*||Equation||Q13|| || || ||{Q13}||{Q13.shown}||{Q13&amp;gt;5}&lt;br /&gt;
|-&lt;br /&gt;
|~124~||File Upload (records number of files uploaded)||Q14|| || || ||{Q14}|| ||{Q14&amp;gt;0}&lt;br /&gt;
|-&lt;br /&gt;
|G||Gender Drop-Down List||Q15|| ||M,F|| ||{Q15}||{Q15.shown}||{Q15==&#039;M&#039;}&lt;br /&gt;
|-&lt;br /&gt;
|U||Huge Free Text||Q16|| || || ||{Q16}||{Q16.shown}||{strlen(Q16)&amp;gt;100}&lt;br /&gt;
|-&lt;br /&gt;
|I||Language Question||Q17|| || || ||{Q17}||{Q17.shown}||{Q17==&#039;en&#039;}&lt;br /&gt;
|-&lt;br /&gt;
|!||List - Dropdown||Q18|| ||1-5|| ||{Q18}||{Q18.shown}||{Q18==3}&lt;br /&gt;
|-&lt;br /&gt;
|L||List Drop-Down/Radio-Button List||Q19|| ||A-Z|| ||{Q19}||{Q19.shown}||{Q19==&#039;X&#039;}&lt;br /&gt;
|-&lt;br /&gt;
|O||List With Comment Drop-Down/Radio-Button List + Textarea||Q20|| ||A-F|| ||{Q20},{Q20comment}||{Q20.shown}||{Q20==&#039;B&#039;}&lt;br /&gt;
|-&lt;br /&gt;
|T||Long Free Text||Q21|| || || ||{Q21}||{Q21.shown}||{strstr(Q21,&#039;hello&#039;)&amp;gt;0}&lt;br /&gt;
|-&lt;br /&gt;
|M||Multiple Choice Checkbox||Q22||A-F, other|| || ||{Q22_E}, {Q22_other}||{Q22_E.shown}, {Q22_other}||{Q22_E==&#039;Y&#039;}&lt;br /&gt;
|-&lt;br /&gt;
|P||Multiple Choice With Comments Checkbox + Text||Q23||A-F|| || ||{Q23_D}, {Q23_Dcomment}||{Q23_D.shown}||{!is_empty(Q23)}&lt;br /&gt;
|-&lt;br /&gt;
|K||Multiple Numerical Question||Q24||self,mom,dad|| || ||{Q24_self}||{Q24_self.shown}||{Q24_self&amp;gt;30}&lt;br /&gt;
|-&lt;br /&gt;
|Q||Multiple Short Text||Q25||A-F|| || ||{Q25_B}||{Q25_B.shown}||{substr(Q25_B,1,1)==&#039;Q&#039;}&lt;br /&gt;
|-&lt;br /&gt;
|N||Numerical Question Type||Q26|| || || ||{Q26}||{Q26.shown}||{Q26 &amp;gt; 30}&lt;br /&gt;
|-&lt;br /&gt;
|R||Ranking Style||Q27||1-4|| || ||{Q27_1}||{Q27_1.shown}||{Q27_1==3}&lt;br /&gt;
|-&lt;br /&gt;
|S||Short Free Text||Q28|| || || ||{Q28}||{Q28.shown}||{Q28==&#039;mine&#039;}&lt;br /&gt;
|-&lt;br /&gt;
|Y||Yes/No Radio-Buttons||Q29|| || || ||{Q29}||{Q29.shown}||{Q29==&#039;Y&#039;}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==The reserved &#039;this&#039;, &#039;self&#039;, and &#039;that&#039; variables== &amp;lt;!--T:157--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:158--&amp;gt;&lt;br /&gt;
Quite often, you want to evalute all parts of a question, such as counting how many sub-questions have been answered, or summing the scores.  Other times, you want to process just certain rows or columns of a question (such as getting the row or column sums and storing them in the database).  These reserved variables make that process relatively painless.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:159--&amp;gt;&lt;br /&gt;
The &#039;this&#039; variable is used exclusively within the &amp;quot;Whole question validation equation&amp;quot; and &amp;quot;Sub-question validation equation&amp;quot; advanced question options.  It expands to the variable names of each of the cells within those questions.  So, if you want to make sure that each entry is greater than three, you would set the &amp;quot;Sub-question validation equation&amp;quot; to (this &amp;gt; 3).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:160--&amp;gt;&lt;br /&gt;
The &#039;self&#039; and &#039;that&#039; variable are more powerful, and serve as macros which are expanded prior to processing equations.  The syntax choices are:&lt;br /&gt;
*self&lt;br /&gt;
*self.&#039;&#039;suffix&#039;&#039;&lt;br /&gt;
*self.&#039;&#039;sub-selector&#039;&#039;&lt;br /&gt;
*self.&#039;&#039;sub-selector&#039;&#039;.&#039;&#039;suffix&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:161--&amp;gt;&lt;br /&gt;
&#039;&#039;suffix&#039;&#039; is any of the normal qcode suffixes (e.g. NAOK, value, shown)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:162--&amp;gt;&lt;br /&gt;
&#039;&#039;sub-selector&#039;&#039; is one of:&lt;br /&gt;
*comments - only subquestions that are comments (e.g. from multiple choice with comment and list with comment)&lt;br /&gt;
*nocomments - only subquestions that are not comments&lt;br /&gt;
*sq_X - where X is a row or column identifier.  Only sub-questions matching pattern X are selected. Note that search is done on complete code identifier, then sq_X match and include subquestions nX, X, Xn (e.g. if you use sq_1, subquestions a1, 1a, 1, 11 or 001 was included). Put attention at dual scale question type where subquestions code are QCODE_SQCODE_1 and QCODE_SQCODE_1 and to ranking question type where subquestions code are QCODE_1,QCODE_2 ....&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:163--&amp;gt;&lt;br /&gt;
Examples:&lt;br /&gt;
*Has any part of a question been answered?  {count(self.NAOK)&amp;gt;0}&lt;br /&gt;
*What is the assessment score for this question?  {sum(self.value)}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:164--&amp;gt;&lt;br /&gt;
You can also use these to get row and column totals.  Say you have a array of numbers with rows A-E and columns 1-5.&lt;br /&gt;
*What is the grand total?  {sum(self.NAOK)}&lt;br /&gt;
*What is the total of row B?  {sum(self.sq_B.NAOK)}&lt;br /&gt;
*What is the total of column 3? {sum(self.sq_3.NAOK)}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:165--&amp;gt;&lt;br /&gt;
The &#039;that&#039; variable is like the &#039;self&#039; variable, but lets you refer to other questions.  Its syntax is:&lt;br /&gt;
*that.&#039;&#039;qname&#039;&#039;&lt;br /&gt;
*that.&#039;&#039;qname&#039;&#039;.&#039;&#039;suffix&#039;&#039;&lt;br /&gt;
*that.&#039;&#039;qname&#039;&#039;.&#039;&#039;sub-selector&#039;&#039;&lt;br /&gt;
*that.&#039;&#039;qname&#039;&#039;.&#039;&#039;sub-selector&#039;&#039;.&#039;&#039;suffix&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:166--&amp;gt;&lt;br /&gt;
&#039;&#039;qname&#039;&#039; is the question name without any sub-question extensions.  So, say you create a question &#039;q1&#039;, that is its &#039;&#039;qname&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:167--&amp;gt;&lt;br /&gt;
Examples:&lt;br /&gt;
*Has any part of question q1 been answered?  {count(that.q1.NAOK)&amp;gt;0}&lt;br /&gt;
*What is the assessment score for q2?  {sum(that.q2.NAOK)}&lt;br /&gt;
*What is the grand total of q3? {sum(that.q3.NAOK)}&lt;br /&gt;
*What is the total of row C in q4?  {sum(that.q4.sq_C.NAOK)}&lt;br /&gt;
*What is the total of column 2 in q4? {sum(that.q4.sq_2.NAOK)}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:168--&amp;gt;&lt;br /&gt;
The &#039;self&#039; and &#039;that&#039; variables can be used in any relevance,  validation, or tailoring.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:169--&amp;gt;&lt;br /&gt;
The one caveat is that when you use the [[Show Logic File|Show Logic File]] feature, it will show you the expanded value of &#039;self&#039; and &#039;that&#039;.  This lets you see the actual equation that will be generated so that you (and Expression Manager) can validate that the variables exist.  This may seem confusing since you may see quite lenghty equations.  However, if you edit the question, you will see the original equation using &#039;self&#039; and/or &#039;that&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:170--&amp;gt;&lt;br /&gt;
Also note that you should not use these variables if (a) you want to explicitly name each variable used in an equation, or (b) use variables that do not have sub-questions (e.g. single response questions).  In those cases, prefixing a variable with &#039;that&#039; is overkill, and you run the risk of getting unexpected results.&lt;br /&gt;
&lt;br /&gt;
==Usage of NAOK== &amp;lt;!--T:218--&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:219--&amp;gt;&lt;br /&gt;
When you put some variable from question in any equation : if this question (or subquestion) is hidden by condition : this disable all equation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:220--&amp;gt;&lt;br /&gt;
For example : count(Q1_SQ1,Q1_SQ2,Q1_SQ3,Q1_SQ4) give always an empty string if one subquestion of Q1 is filtered.&lt;br /&gt;
To count the number of checked subquestion in such question can be count(Q1_SQ1.NAOK,Q1_SQ2.NAOK,Q1_SQ3.NAOK,Q1_SQ4.NAOK). If the sub question is hidden :Exprssion manager return an empty string.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:221--&amp;gt;&lt;br /&gt;
Without NAOK : if one question or one subquestion is hidden : Expression Manager return always an empty string, same to return false.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:222--&amp;gt;&lt;br /&gt;
The .shown always use the NAOK system (empty string if hidden) but if you need the code of the answer : it&#039;s always a good idea to add .NAOK after the question code. Except if you need it and know what you do.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:223--&amp;gt;&lt;br /&gt;
Another example and information is provided at [[#Overriding_Cascading_Conditions|Overriding Cascading Conditions]]  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Access to Functions== &amp;lt;!--T:171--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:172--&amp;gt;&lt;br /&gt;
Expression Manager provides access to mathematical, string, and user-defined functions, as shown below.  It has PHP and JavaScript equivalents for these functions so that they work identically on server-side (PHP) and client-side (JavaScript).  It is easy to add new functions.&lt;br /&gt;
&lt;br /&gt;
===Implemented Functions=== &amp;lt;!--T:173--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:174--&amp;gt;&lt;br /&gt;
The following functions are currently available:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:175--&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Function!!Meaning!!Syntax&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.abs.php abs]||Absolute value||number abs(number)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.acos.php acos]||Arc cosine||number acos(number)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.addslashes.php addslashes]||Quote string with slashes||string addslashes(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.asin.php asin]||Arc sine||number asin(number)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.atan.php atan]||Arc tangent||number atan(number)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.atan2.php atan2]||Arc tangent of two variables||number atan2(number, number)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.ceil.php ceil]||Round fractions up||number ceil(number)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.checkdate.php checkdate]||Returns true(1) if it is a valid date in gregorian calendar||bool checkdate(month,day,year)&lt;br /&gt;
|-&lt;br /&gt;
|convert_value||Convert a numerical value using a inputTable and outputTable of numerical values||number convert_value(fValue, iStrict, sTranslateFromList, sTranslateToList)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.cos.php cos]||Cosine||number cos(number)&lt;br /&gt;
|-&lt;br /&gt;
|count||count the number of answered (non-blank)questions in the list||number count(arg1, arg12, ..., argN)&lt;br /&gt;
|-&lt;br /&gt;
|countif||Count the number of answered questions in the list equal the first argument||number countif(matches, arg1, arg2, ... argN)&lt;br /&gt;
|-&lt;br /&gt;
|countifop||Count the number of answered questions in the list which pass the criteria (arg op value)||number countifop(op, value, arg1, arg2, ... argN)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.date.php date]||Format a local date/time||string date(format &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;, timestamp=time()])&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.exp.php exp]||Calculates the exponent of e||number exp(number)&lt;br /&gt;
|-&lt;br /&gt;
|fixnum||Display numbers with comma as radix separator, if needed||string fixnum(number)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.floor.php floor]||Round fractions down||number floor(number)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.gmdate.php gmdate]||Format a GMT date/time||string gmdate(format &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;, timestamp=time()])&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.html-entity-decode.php html_entity_decode]||Convert all HTML entities to their applicable characters (always uses ENT_QUOTES and UTF-8)||string html_entity_decode(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.htmlentities.php htmlentities]||Convert all applicable characters to HTML entities (always uses ENT_QUOTES and UTF-8)||string htmlentities(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.htmlspecialchars.php expr_mgr_htmlspecialchars]||Convert special characters to HTML entities (always uses ENT_QUOTES and UTF-8)||string htmlspecialchars(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.htmlspecialchars-decode.php expr_mgr_htmlspecialchars_decode]||Convert special HTML entities back to characters (always uses ENT_QUOTES and UTF-8)||string htmlspecialchars_decode(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.idate.php idate]||Format a local time/date as integer||string idate(string &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;, timestamp=time()])&lt;br /&gt;
|-&lt;br /&gt;
|if||Excel-style if(test,result_if_true,result_if_false)||if(test,result_if_true,result_if_false)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.implode.php implode]||Join array elements with a string||string implode(glue,arg1,arg2,...,argN)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.intval.php intval]||Get the integer value of a variable||int intval(number &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;, base=10])&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.empty.php is_empty]||Determine whether a variable is considered to be empty||bool is_empty(var)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.is-float.php is_float]||Finds whether the type of a variable is float||bool is_float(var)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.is-int.php is_int]||Find whether the type of a variable is integer||bool is_int(var)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.is-nan.php is_nan]||Finds whether a value is not a number||bool is_nan(var)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.is-null.php is_null]||Finds whether a variable is NULL||bool is_null(var)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.is-numeric.php is_numeric]||Finds whether a variable is a number or a numeric string||bool is_numeric(var)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.is-string.php is_string]||Find whether the type of a variable is string||bool is_string(var)&lt;br /&gt;
|-&lt;br /&gt;
|join{{NewIn|2.0|b=130129}}||Join elements as a new string||join(arg1, arg2, ... argN)&lt;br /&gt;
|-&lt;br /&gt;
|list||Return comma-separated list of non-blank values||string list(arg1, arg2, ... argN)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.log.php log]|| The logarithm of number to base, if given, or the natural logarithm. ||number log(number,base=e)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.ltrim.php ltrim]||Strip whitespace (or other characters) from the beginning of a string||string ltrim(string &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;, charlist])&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.max.php max]||Find highest value||number max(arg1, arg2, ... argN)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.min.php min]||Find lowest value||number min(arg1, arg2, ... argN)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.mktime.php mktime]||Get UNIX timestamp for a date (each of the 6 arguments are optional)||number mktime([hour [, minute [, second [, month [, day [, year ]]]]]])&lt;br /&gt;
|-&lt;br /&gt;
|modulo-function||The modulo function is &#039;&#039;&#039;not supported&#039;&#039;&#039; yet. You can use the floor() function instead||floor(x/y)==(x/y)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.nl2br.php nl2br]||Inserts HTML line breaks before all newlines in a string||string nl2br(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.number-format.php number_format]||Format a number with grouped thousands||string number_format(number)&lt;br /&gt;
|-&lt;br /&gt;
|pi||Get value of pi||number pi()&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.pow.php pow]||Exponential expression||number pow(base, exp)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.quoted-printable-decode.php quoted_printable_decode]||Convert a quoted-printable string to an 8 bit string||string quoted_printable_decode(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.quoted-printable-encode.php quoted_printable_encode]||Convert a 8 bit string to a quoted-printable string||string quoted_printable_encode(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.quotemeta.php quotemeta]||Quote meta characters||string quotemeta(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.rand.php rand]||Generate a random integer, see [[Expression Manager Sample Surveys#Randomly Ask One Question Per Group|this example]]||int rand() OR int rand(min, max)&lt;br /&gt;
|-&lt;br /&gt;
|regexMatch||compare a string to a [[Using regular expressions|regular expression]]||bool regexMatch(pattern,input)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.round.php round]||Rounds a number to an optional precision||number round(val &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;, precision])&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.rtrim.php rtrim]||Strip whitespace (or other characters) from the end of a string||string rtrim(string &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;, charlist])&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.sin.php sin]||Sine||number sin(arg)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.sprintf.php sprintf]||Return a formatted string||string sprintf(format, arg1, arg2, ... argN)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.sqrt.php sqrt]||Square root||number sqrt(arg)&lt;br /&gt;
|-&lt;br /&gt;
|stddev||Calculate the Sample Standard Deviation for the list of numbers||number stddev(arg1, arg2, ... argN)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.str-pad.php str_pad]||Pad a string to a certain length with another string||string str_pad(input, pad_length &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;, pad_string])&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.str-repeat.php str_repeat]||Repeat a string||string str_repeat(input, multiplier)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.str-replace.php str_replace]||Replace all occurrences of the search string with the replacement string||string str_replace(search, replace, subject)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.strcasecmp.php strcasecmp]||Binary safe case-insensitive string comparison||int strcasecmp(str1, str2)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.strcmp.php strcmp]||Binary safe string comparison||int strcmp(str1, str2)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.strip-tags.php strip_tags]||Strip HTML and PHP tags from a string||string strip_tags(str, allowable_tags)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.stripos.php stripos]||Find position of first occurrence of a case-insensitive unicode string (starting by 0, return false if not found)|||int stripos(haystack, needle &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;, offset=0])&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.stripslashes.php stripslashes]||Un-quotes a quoted string||string stripslashes(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.stristr.php stristr]||Case-insensitive strstr||string stristr(haystack, needle &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;, before_needle=false])&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.strlen.php strlen]||Get string length||int strlen(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.strpos.php strpos]||Find position of first occurrence of an unicode string (starting by 0, return false if not found)||int strpos(haystack, needle &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt; offset=0])&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.strrev.php strrev]||Reverse a string||string strrev(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.strstr.php strstr]||Find first occurrence of a string||string strstr(haystack, needle&amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;, before_needle=false])&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.strtolower.php strtolower]||Make a string lowercase||string strtolower(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.strtotime.php strtotime]||Parse about any English textual datetime description into a Unix timestamp||int strtotime(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.strtoupper.php strtoupper]||Make a string uppercase||string strtoupper(string)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.substr.php substr]||Return part of an unicode string||string substr(string, start &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;, length])&lt;br /&gt;
|-&lt;br /&gt;
|sum||Calculate the sum of values in an array||number sum(arg1, arg2, ... argN)&lt;br /&gt;
|-&lt;br /&gt;
|sumifop||Sum the values of answered questions in the list which pass the criteria (arg op value)||number sumifop(op, value, arg1, arg2, ... argN)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.tan.php tan]||Tangent||number tan(arg)&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.time.php time]||Return current UNIX timestamp||number time()&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.trim.php trim]||Strip whitespace (or other characters) from the beginning and end of a string||string trim(string &amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;, charlist])&lt;br /&gt;
|-&lt;br /&gt;
|[http://www.php.net/manual/en/function.ucwords.php ucwords]||Uppercase the first character of each word in a string||string ucwords(string)&lt;br /&gt;
|-&lt;br /&gt;
|unique||Returns true if all non-empty responses are unique||boolean unique(arg1, ..., argN)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Functions that are Planned or Being Considered=== &amp;lt;!--T:176--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:177--&amp;gt;&lt;br /&gt;
Other functions that are planned (or being considered) but which are not implemented yet include the following.  Some of these are for backwards compatability with another survey tool.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:178--&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Syntax!!Meaning!!Comments&lt;br /&gt;
|-&lt;br /&gt;
|e()||returns the value of e||&lt;br /&gt;
|-&lt;br /&gt;
|formatDate(X,PAT)||return the string value of date X formatted according to Java data format pattern PAT||&lt;br /&gt;
|-&lt;br /&gt;
|formatNumber(X,PAT)||return the string value of number X formatted according to Java number format pattern PAT||&lt;br /&gt;
|-&lt;br /&gt;
|getAnsOption(X)||returns the text corresponding to the selected option for answer X||this is the same as X.shown&lt;br /&gt;
|-&lt;br /&gt;
|getAnsOption(X,Y)||returns the text corresponding to the option at index Y of node X||&lt;br /&gt;
|-&lt;br /&gt;
|getRelevance(X)||returns the relevance equation for question X||&lt;br /&gt;
|-&lt;br /&gt;
|getStartTime()||returns the date corresponding to the system time when the interview was started||&lt;br /&gt;
|-&lt;br /&gt;
|getType(X)||returns the string name of the datatype - e.g. *NA* if isNA()||&lt;br /&gt;
|-&lt;br /&gt;
|gotoFirst()||jumps to the first relevant set of questions - this violates the normal flow of the system||&lt;br /&gt;
|-&lt;br /&gt;
|gotoNext()||jumps to the next set of relevant questions - this violates the normal flow of the system||&lt;br /&gt;
|-&lt;br /&gt;
|gotoPrevious()||jumps to the previous set of relevant questions - this violates the normal flow of the system||&lt;br /&gt;
|-&lt;br /&gt;
|isAsked(X)||returns true if the answer is neither *NA*, *INVALID*, nor *UNASKED*||&lt;br /&gt;
|-&lt;br /&gt;
|isInvalid(X)||returns true if the answer is of type *INVALID*||&lt;br /&gt;
|-&lt;br /&gt;
|isNA(X)||returns true if the answer is of type *NA*||&lt;br /&gt;
|-&lt;br /&gt;
|isNotUnderstood(X)||returns true if the answer if of type *HUH*||&lt;br /&gt;
|-&lt;br /&gt;
|isRefused(X)||returns true if the answer is of type *REFUSED*||&lt;br /&gt;
|-&lt;br /&gt;
|isSpecial(X)||returns true if the answer is of type *UNASKED*, *NA*, *REFUSED*, *INVALID*, *UNKNOWN*, or *HUH*||&lt;br /&gt;
|-&lt;br /&gt;
|isUnknown(X)||returns true if the answer is of type *UNKNOWN*||&lt;br /&gt;
|-&lt;br /&gt;
|jumpTo(X)||jump to the group containing the named question -- this violates the normal flow of the system||&lt;br /&gt;
|-&lt;br /&gt;
|jumpToFirstUnasked()||jump to the first unasked question &amp;lt;strike&amp;gt; thus bypassing previous answered questions &amp;lt;/strike&amp;gt; this violates the normal flow of the system||&lt;br /&gt;
|-&lt;br /&gt;
|lastIndexOf(X,Y)||returns the last index (base 0) of string Y in string X. Returns -1 if Y is not contained within X||&lt;br /&gt;
|-&lt;br /&gt;
|list(X,...)||a string containing a comma separated list of the positive values with &amp;quot;and&amp;quot; separating the last two||&lt;br /&gt;
|-&lt;br /&gt;
|mean(X,...)||returns the mean of a list of values||&lt;br /&gt;
|-&lt;br /&gt;
|numAnsOptions(X)||returns the number of answer options that question X has||&lt;br /&gt;
|-&lt;br /&gt;
|orlist(X,...)||a string containing a comma separated list of the positive values, with &amp;quot;or&amp;quot; separting the last two||&lt;br /&gt;
|-&lt;br /&gt;
|parseDate(X,PAT)||returns the date value of string X parsed with Java date format pattern PAT||&lt;br /&gt;
|-&lt;br /&gt;
|parseNumber(X,PAT)||returns the numerical value of string X parsed with Java number format pattern PAT||&lt;br /&gt;
|-&lt;br /&gt;
|showAllResponsesExcept( questionList,attributeList,attributeTitleList)||questionList = pipe-delimited list of question identifiers; attributeList = pipe-delimited list of attributes (like question#, title, text, type - so you can decide what to show); attributeTitleList = pipe-delimited list of table headers, so can internationalize the report.||&lt;br /&gt;
|-&lt;br /&gt;
|showTheseResponses( questionList,attributeList,attributeTitleList)||questionList = pipe-delimited list of question identifiers; attributeList = pipe-delimited list of attributes (like question#, title, text, type - so you can decide what to show); attributeTitleList = pipe-delimited list of table headers, so can internationalize the report.|| &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Expression Manager Knows Which Variables are Local== &amp;lt;!--T:179--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:180--&amp;gt;&lt;br /&gt;
In order to properly build the JavaScript for page, Expression Manager needs to know which variables are set on the page, and what their JavaScript ID is (e.g. for document.getElementById(x)).  It also must know which variables are set on other pages (so that it can ensure that the needed &amp;lt;input type=&#039;hidden&#039; value=&#039;x&#039;&amp;gt; fields are present and populated).&lt;br /&gt;
&lt;br /&gt;
==Cascading Conditions== &amp;lt;!--T:181--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:182--&amp;gt;&lt;br /&gt;
If any of the variables are irrelevant, the whole equation will be irrelevant (false).  For example, in the following table, N/A means that one of the variables was not relevant&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:183--&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Operator!!Example!!a!!b!!Result&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;+ (unary)&amp;lt;/nowiki&amp;gt;||&amp;lt;nowiki&amp;gt;+a&amp;lt;/nowiki&amp;gt;||N/A|| ||false&lt;br /&gt;
|-&lt;br /&gt;
|- (unary)||-a||N/A|| ||false&lt;br /&gt;
|-&lt;br /&gt;
|!||!a||N/A|| ||false&lt;br /&gt;
|-&lt;br /&gt;
|== (or eq)||a == b||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|== (or eq)||a == b||N/A||0||false&lt;br /&gt;
|-&lt;br /&gt;
|== (or eq)||a == b||N/A||N/A||false&lt;br /&gt;
|-&lt;br /&gt;
|!= (or ne)||a != b||N/A||5|| false&lt;br /&gt;
|-&lt;br /&gt;
|!= (or ne)||a != b||N/A||N/A|| false&lt;br /&gt;
|-&lt;br /&gt;
|!= (or ne)||a != b||N/A||0||false&lt;br /&gt;
|-&lt;br /&gt;
|&amp;gt; (or gt)||a &amp;gt; b||N/A||5|| false&lt;br /&gt;
|-&lt;br /&gt;
|&amp;gt;= (or ge)||a &amp;gt;= b||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt; (or lt)||a &amp;lt; b||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;= (or le)||a &amp;lt;= b||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|and||a and b||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|and||a and b||N/A||N/A||false&lt;br /&gt;
|-&lt;br /&gt;
|or||a or b||N/A||N/A||false&lt;br /&gt;
|-&lt;br /&gt;
|or||a or b||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;nowiki&amp;gt;+&amp;lt;/nowiki&amp;gt;||a + b||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|-||a - b||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|*||a * b||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|/||a / b||5||N/A||false&lt;br /&gt;
|-&lt;br /&gt;
|()||(a)||N/A|| ||false&lt;br /&gt;
|-&lt;br /&gt;
|(exp)||(a &amp;amp;&amp;amp; b)||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|(exp) op (exp)||(b + b) &amp;gt; (a &amp;amp;&amp;amp; b)||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|function||sum(a,b,b)||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|function||max(a,b)||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|function||min(a,b)||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|function||implode(&#039;, &#039;,a,b,a,b)||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|function||if(a,a,b)||N/A||5||false&lt;br /&gt;
|-&lt;br /&gt;
|function||is_empty(a)||N/A|| ||false&lt;br /&gt;
|-&lt;br /&gt;
|function||is_empty(a)||0 (or blank)|| ||true&lt;br /&gt;
|-&lt;br /&gt;
|function||!is_empty(a)||N/A|| ||false&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Overriding Cascading Conditions=== &amp;lt;!--T:184--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:185--&amp;gt;&lt;br /&gt;
Say you want to show a running total of all relevant answers.  You might try to use the equation {sum(q1,q2,q3,...,qN)}.  However, this gets translated internally to LEMif(LEManyNA(&#039;q1&#039;,&#039;q2&#039;,&#039;q3&#039;,...,&#039;qN&#039;),&#039;&#039;,sum(LEMval(&#039;q1&#039;),LEMval(&#039;q2&#039;),LEMval(&#039;q3&#039;),...,LEMval(&#039;qN&#039;))).  So, if any of the values q1-qN are irrelevant, the equation will always return false.  In this case, the sum() will show 0 until all questions are answered.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:186--&amp;gt;&lt;br /&gt;
To get around this, each variable can have a &amp;quot;.NAOK&amp;quot; suffix (meaning that Not Applicable is OK) added to it.  In such cases, the following behavior occurs.  Say you have a variable q1.NAOK&lt;br /&gt;
#q1 is not added to the LEManyNA() clause&lt;br /&gt;
#LEMval(&#039;q1&#039;) will  continue to check whether the response is relevant, and will return &amp;lt;nowiki&amp;gt;&#039;&#039;&amp;lt;/nowiki&amp;gt; if it is not (so individual irrelevant responses will be ignored, but they will not void the entire expression).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:187--&amp;gt;&lt;br /&gt;
So, the solution to the running total problem is to use the equation sum(q1.NAOK,q2.NAOK,q3.NAOK,...,qN.NAOK).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:188--&amp;gt;&lt;br /&gt;
The use of the .NAOK suffix also lets authors design surveys that have several possible paths but then converge on common paths later.  For example, say subjects answer a survey in a way that is outside the normal range of responses.  The author could alert the subjects that they may not get valid results, and ask them whether they really want to  continue with the survey.  If they say Yes, then the rest of the questions will be shown.  The condition for the &amp;quot;rest of the questions&amp;quot; would check whether the initial responses were answered within the normal range OR whether the subject said Yes to the question that is only relevant if they answered outside the normal range.&lt;br /&gt;
&lt;br /&gt;
==How does Expression Manager Support Conditional Micro-Tailoring?== &amp;lt;!--T:189--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:190--&amp;gt;&lt;br /&gt;
Here is an example of micro-tailoring (where Question Type==&#039;expr&#039; means an Equation):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:191--&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Question Code!!Relevance!!Question Type!!Question&lt;br /&gt;
|-&lt;br /&gt;
|name||1||text||What is your name?&lt;br /&gt;
|-&lt;br /&gt;
|age||1||text||How old are you?&lt;br /&gt;
|-&lt;br /&gt;
|badage||!is_empty(age)||expr||{(age&amp;lt;16) or (age&amp;gt;80)}&lt;br /&gt;
|-&lt;br /&gt;
|agestop||badage||message||Sorry, {name}, you are too {if( (age&amp;lt;16),&#039;young&#039;,if( (age&amp;gt;80),&#039;old&#039;,&#039;middle-aged&#039;) ) } for this test.&lt;br /&gt;
|-&lt;br /&gt;
|kids||!badage||yesno||Do you have children?&lt;br /&gt;
|-&lt;br /&gt;
|parents||1||expr||{!badage &amp;amp;&amp;amp; kids==&#039;Y&#039;}&lt;br /&gt;
|-&lt;br /&gt;
|numKids||parents||text||How many children do you have?&lt;br /&gt;
|-&lt;br /&gt;
|kid1||parents &amp;amp;&amp;amp; numKids &amp;gt;= 1||text||How old is your first child?&lt;br /&gt;
|-&lt;br /&gt;
|kid2||parents &amp;amp;&amp;amp; numKids &amp;gt;= 2||text||How old is your second child?&lt;br /&gt;
|-&lt;br /&gt;
|kid3||parents &amp;amp;&amp;amp; numKids &amp;gt;= 3||text||How old is your third child?&lt;br /&gt;
|-&lt;br /&gt;
|kid4||parents &amp;amp;&amp;amp; numKids &amp;gt;= 4||text||How old is your fourth child?&lt;br /&gt;
|-&lt;br /&gt;
|kid5||parents &amp;amp;&amp;amp; numKids &amp;gt;= 5||text||How old is your fifth child?&lt;br /&gt;
|-&lt;br /&gt;
|sumage||1||expr||{sum(kid1.NAOK,kid2.NAOK,kid3.NAOK,kid4.NAOK,kid5.NAOK)}&lt;br /&gt;
|-&lt;br /&gt;
|report||parents||yesno||{name}, you said you are {age} and that you have {numKids}.  The sum of ages of your first {min(numKids,5)} kids is {sumage}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:192--&amp;gt;&lt;br /&gt;
All of these questions can be on a single page (e.g. in the same group), and only the relevant questions will display.  Moreover, as you enter the ages of children, the sum() expression in the last question will dynamically update on the page.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:193--&amp;gt;&lt;br /&gt;
Expression Manager provides this functionality by surrounding each expression with a named &amp;lt;span&amp;gt; element.  Every time a value changes, it recomputes the expression that should appear in that &amp;lt;span&amp;gt; element and regenerates the display.  You can have dozens, or even hundreds, of such tailored expressions on the same page, and the page will re-display all of them in a single screen refresh.&lt;br /&gt;
&lt;br /&gt;
==Mapping of LimeSurvey 1.91+ to Expression Manager Functionality== &amp;lt;!--T:194--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:195--&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Old Feature!!New Feature!!Comments&lt;br /&gt;
|-&lt;br /&gt;
|Conditions||Relevance||You can use very complex conditional equations, and access a broader range of variables&lt;br /&gt;
|-&lt;br /&gt;
|Assessments||Equation||Any assessment scores can be re-structured into an Equation. This both ensures that the score is written to the database, and also lets you see dynamic changes to the score value on the current page&lt;br /&gt;
|-&lt;br /&gt;
|Replacements||Expression Manager||The core engine takes the input string and treats everything within curly braces as an Expression - so it handles all historical replacements types.  To avoid messing up embedded JavaScript, Expression Manager only processes content between curly braces as long as (a)  there is no leading or trailing whitespace within the curly braces - e.g. {expr} is an expression, but { expr}, {expr }, and { expr } are not expressions.  Furthermore, Expression Manager does not process content within its own strings (e.g. {list(&#039;hi&#039;,&#039;there {braces}&#039;)} generates &amp;quot;hi there {braces}&amp;quot;).  It also ignores escaped curly braces (e.g. \{this is not an expression\})&lt;br /&gt;
|-&lt;br /&gt;
|Validation||Expression Manager||The plan is to take the current min/max Question Attributes and have Expression Manager process them.  That way the min/max values can be expressions themselves&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Syntax Highlighting= &amp;lt;!--T:196--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:197--&amp;gt;&lt;br /&gt;
To help with entering and validating expressions, EM provides syntax highlighting with the following features:&lt;br /&gt;
&lt;br /&gt;
==Types and Meanings of Syntax Highlighting== &amp;lt;!--T:198--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:199--&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Color!!Sample!!Meaning!!Tooltip!!Comments&lt;br /&gt;
|-&lt;br /&gt;
|tan background||style=&#039;background-color: #eee8aa&#039;|Sample||the whole equation||none||Anything within curly braces that is recognized as an equation (e.g. there is no leading or trailing whitepace) will be color-coded with a tan background to help distinguish it from surrounding text&lt;br /&gt;
|-&lt;br /&gt;
|bold red text||style=&#039;color:#ff0000; background-color:#eee8aa&#039;|&#039;&#039;&#039;Sample&#039;&#039;&#039;||An error||Some explanation on error||Can be an unknow variable or an error in function, .... Survey can be totally broken, this don&#039;t show to public user.&lt;br /&gt;
|-&lt;br /&gt;
|blue text||style=&#039;color:#0000ff; background-color:#eee8aa&#039;|Sample||function name||meaning and allowable syntax||function names, or things that should be functions since they are followed by an opening parenthesis, are presented in bold blue text.  Tooltips show the meaning and allowable syntax for the function.&lt;br /&gt;
|-&lt;br /&gt;
|grey text||style=&#039;color:#808080; background-color:#eee8aa&#039;|Sample||string||none||single and double-quoted strings are shown in grey text&lt;br /&gt;
|-&lt;br /&gt;
|cyan text||style=&#039;color:#4169e1; background-color:#eee8aa&#039;|Sample||variable set on the same page,||&amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;name or SGQA code]: question; value; answerList showing codes for each value||Any variable that is set on the same page to the current question is shown in cyan text, showning it can be updated in javascript.  The tooltip shows its name (if you used INSERTANS:xxx) or SGQA code (if you used the new naming system), the actual question, and its current value (or blank if not set).  If the question type expects responses from an enumerated value set, the mapping of the codes to display values is show.&lt;br /&gt;
|-&lt;br /&gt;
|green text||style=&#039;color:#008000; background-color:#eee8aa&#039;|Sample||variable set on a prior page||&amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;name or SGQA code]: question; value; answerList showing codes for each value||Any variable that is set on a prior page is shown in bold green text.  The tooltip shows its name (if you used INSERTANS:xxx) or SGQA code (if you used the new naming system), the actual question, and its current value (or blank if not set).  If the question type expects responses from an enumerated value set, the mapping of the codes to display values is show.&lt;br /&gt;
|-&lt;br /&gt;
|bold pink text||style=&#039;color:#9370db; background-color:#eee8aa&#039;|Sample||variable set on a later page &amp;lt;sup&amp;gt;in general : empty at survey start, but can be filled with index or move previous&amp;lt;/sup&amp;gt;||&amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;name or SGQA code]: question; value; answerList showing codes for each value||Any variable that is set on a prior page is shown in bold pink text.  These are erorrs since the variable is  being used before it is declareed.  The tooltip shows its name (if you used INSERTANS:xxx) or SGQA code (if you used the new naming system), the actual question, and its current value (or blank if not set).  If the question type expects responses from an enumerated value set, the mapping of the codes to display values is show.&lt;br /&gt;
|-&lt;br /&gt;
|bold tan text||style=&#039;color:#a0522d; background-color:#eee8aa&#039;|Sample||a lime replacement value||the value||Lime Replacement Strings (like {TOKEN:xxx}, {PRIVACY_MESSAGE}) are shown in bold tan text.  &lt;br /&gt;
|-&lt;br /&gt;
|red text||style=&#039;color:#ff4500; background-color:#eee8aa&#039;|Sample||assignment operator (=) ||warning message||If you use one of the assignment operator (=) that operator will be displayed in red text.  This is meant to help prevent accidental re-assignment of values when you really meant to check whether a == b instead of  setting the value of a = b.&lt;br /&gt;
|-&lt;br /&gt;
|normal black text||style=&#039;color:black; background-color:#eee8aa&#039;|Sample||punctuation||none||All other punctuation within the expression is shown as normal black text.&lt;br /&gt;
|-&lt;br /&gt;
|red-boxed text||a bold red line surrounds the error||syntax error||description of the error||Any detected syntax errors are shown by surrounding the error with a red box.  The tooltip shows the error.  Examples include unmatched parentheses, use of undefined functions, passing the wrong number of arguments to functions, poorly structured expressions (e.g. missing operators between variables), trying to assign a new value to a read-only variable, trying to assign values to non-variables, or using unsupported syntax.  Note that the syntax error dectection system may only report one error in an expression even if there are multiple errors; however, if any errors are detected, at least one error will be shown.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Additional Reading= &amp;lt;!--T:202--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==[[Expression Manager Sample Surveys|Expression Manager Sample Surveys]]== &amp;lt;!--T:203--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==[[Expression Manager HowTos|Use Cases and HowTos]]== &amp;lt;!--T:204--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==[[Expression Manager Examples|Step-by-Step Examples]].== &amp;lt;!--T:205--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==[[Expression Manager for developers|Reference for Developers]]== &amp;lt;!--T:206--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==[[Expression Manager Roadmap|RoadMap/Status/ToDo List]]== &amp;lt;!--T:207--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/translate&amp;gt;&lt;/div&gt;</summary>
		<author><name>LimeAJ</name></author>
	</entry>
	<entry>
		<id>https://www.limesurvey.org/manual/index.php?title=Assessments&amp;diff=73646</id>
		<title>Assessments</title>
		<link rel="alternate" type="text/html" href="https://www.limesurvey.org/manual/index.php?title=Assessments&amp;diff=73646"/>
		<updated>2017-05-29T19:12:56Z</updated>

		<summary type="html">&lt;p&gt;LimeAJ: Added some location information, to make it easier for people that don&amp;#039;t know fully the navigation of the settings.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;languages /&amp;gt; &amp;lt;translate&amp;gt;&lt;br /&gt;
&amp;lt;!--T:1--&amp;gt;&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:2--&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;simplebox&amp;quot;&amp;gt;Note: Starting in Version 1.92, you can create more sophisticated assessments and reports using [[Expression Manager|Expression Manager]].  It lets you access all variable types, and easily generate tailored  reports at any point in the survey (not just the end).  Using the new Equation question type, you can have LimeSurvey automatically save your assessment calculate and/or report to the database&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=General= &amp;lt;!--T:3--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:4--&amp;gt;&lt;br /&gt;
LimeSurvey has the ability to create &amp;quot;assessments&amp;quot; on your survey - even for multilingual surveys. Assessments are rules which evaluate the responses to a survey immediately after it is submitted, and then display text blocks to the participant based on that evaluation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:5--&amp;gt;&lt;br /&gt;
An english sample survey demonstrating the use of assessments at LimeSurvey is available for download. You can import this survey at your LimeSurvey system for testing (&amp;quot;import&amp;quot; tab at survey creation page): [[File:Limesurvey_sample_survey_Assessment.lss]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:6--&amp;gt;&lt;br /&gt;
As an example, consider the following: You have two questions in your survey, the first question asks if the user smokes: &amp;quot;Do you smoke?&amp;quot;. The question has 3 possible answers, &amp;quot;Yes more than 10 per day&amp;quot; with an answer code of &amp;quot;10&amp;quot;, &amp;quot;Yes, but less than 10 per day&amp;quot; with an answer code of &amp;quot;5&amp;quot; and &amp;quot;No, I don&#039;t smoke at all&amp;quot; with an answer code of &amp;quot;1&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:7--&amp;gt;&lt;br /&gt;
The second question &amp;quot;Do you exercise?&amp;quot; has three possible answers; &amp;quot;Yes, I exercise for at least half an hour three times a week&amp;quot; with a value of &amp;quot;1&amp;quot;, &amp;quot;Yes, I exercise every now and then&amp;quot; with a value of &amp;quot;5&amp;quot; and &amp;quot;No, I don&#039;t ever do any exercise&amp;quot; with an answer code/value of &amp;quot;10&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:8--&amp;gt;&lt;br /&gt;
If we were to add the totals of the values for each possible answer at the end of the survey, we&#039;d have a good indication of the general health of the respondent. Someone who smokes and doesn&#039;t ever do any exercise will have scored 10 in each of their answers, giving a sum of 20 when we add the values together. Someone who doesn&#039;t smoke and exercises regularly will have scored 1 in each of the answers with a total of 2 when we add the values together.&lt;br /&gt;
&lt;br /&gt;
=How to use= &amp;lt;!--T:9--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Activate assessments== &amp;lt;!--T:10--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:11--&amp;gt;&lt;br /&gt;
To be able to see and edit assessments for answers visit the survey settings and change the setting &#039;&#039;&#039;Use assessments?&#039;&#039;&#039; in the &#039;&#039;&#039;[[Creating_a_new_survey#Notification_.26_data_management|Notification &amp;amp; data management]]&#039;&#039;&#039; tab to &#039;On&#039;. After that you will be presented with additional fields when editing answers.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:12--&amp;gt;&lt;br /&gt;
In [[Label sets|label sets]] these fields are always visible.&lt;br /&gt;
&lt;br /&gt;
==Set assessment values for each answer/label== &amp;lt;!--T:13--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:31--&amp;gt;&lt;br /&gt;
[[File:Assesment_value_set.png|thumb|Set the assessment value]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:14--&amp;gt;&lt;br /&gt;
The assessments tool allows you to set some rules based on the summed assessment values of the questions in the survey, either for the total survey, or for each group within the survey. If you now edit an answer of a question you will see an additional field right beside each code field where you can set an assessment value for this answer.&lt;br /&gt;
&lt;br /&gt;
==How question types are evaluated== &amp;lt;!--T:16--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:17--&amp;gt;&lt;br /&gt;
There are certain [[question types]] which will not be assessed or will be assessed in a special way. Most question types that are not being assessed are convenience question types and can be replaced with a assessable question type - for example a 5 point choice can always be replaced with a simple radio single select question type.&lt;br /&gt;
&lt;br /&gt;
===Question types being assessed=== &amp;lt;!--T:18--&amp;gt;&lt;br /&gt;
*Array (Flexible labels) dual scale&lt;br /&gt;
*Array (Flexible labels)&lt;br /&gt;
*Array (Flexible labels) by column&lt;br /&gt;
*List (Flexible labels) (Dropdown)&lt;br /&gt;
*List (Flexible labels) (Radio)&lt;br /&gt;
*List (Dropdown)&lt;br /&gt;
*List (Radio)&lt;br /&gt;
*List with comment&lt;br /&gt;
*Multiple options&lt;br /&gt;
*Multiple options with comments&lt;br /&gt;
&lt;br /&gt;
===Question types not being assessed by values set in answers or label set=== &amp;lt;!--T:19--&amp;gt;&lt;br /&gt;
*Array (Multi Flexible) (Numbers)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:20--&amp;gt;&lt;br /&gt;
With this question type the chosen values in the select boxes will used as the value for assessment.&lt;br /&gt;
&lt;br /&gt;
===Question types not being assessed=== &amp;lt;!--T:21--&amp;gt;&lt;br /&gt;
* 5 point choice&lt;br /&gt;
* Array (5 point choice)&lt;br /&gt;
* Array (10 point choice)&lt;br /&gt;
* Array (Increase, Same, Decrease)&lt;br /&gt;
* Array (Multi flexible) (Text)&lt;br /&gt;
* Array (Yes/No/Uncertain)&lt;br /&gt;
* Boilerplate question&lt;br /&gt;
* Date&lt;br /&gt;
* Gender&lt;br /&gt;
* Huge free text&lt;br /&gt;
* Language switch&lt;br /&gt;
* Long free text&lt;br /&gt;
* Multiple numerical input&lt;br /&gt;
* Numerical input&lt;br /&gt;
* Ranking&lt;br /&gt;
* Short free text&lt;br /&gt;
* Yes/No&lt;br /&gt;
&lt;br /&gt;
==Define assessment rules== &amp;lt;!--T:22--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:23--&amp;gt;&lt;br /&gt;
Now you want to define rules on the assessment values - to do this click the assessment icon [[File:assessments.png]] in one of the menus on the survey administration toolbar. From this screen you can view, edit or delete existing assessments or create new assessments.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:24--&amp;gt;&lt;br /&gt;
In the &amp;quot;Add/Edit&amp;quot; box you can choose the following:&lt;br /&gt;
*Scope: The scope of the assessment. Choose either &amp;quot;Total&amp;quot; which will create an assessment based on the sum of all the answers in the entire survey, or &amp;quot;Group&amp;quot; which will create an assessment based on the sum of all the answers in a group (chosen in the next row)&lt;br /&gt;
*Group: If the scope of this assessment is for the current &amp;quot;Group&amp;quot;, this is where you choose which group to assess.&lt;br /&gt;
*Minimum: The minimum &amp;quot;sum&amp;quot; of answers to which this assessment will apply&lt;br /&gt;
*Maximum: The maximum &amp;quot;sum&amp;quot; of answers to which this assessment will apply&lt;br /&gt;
*Heading: The heading of the assessment which will display if this assessment is shown&lt;br /&gt;
*Message: The actual message for this assessment. Inside the message you can use the tags {PERC} or {TOTAL} to show the related score in that particular message.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:25--&amp;gt;&lt;br /&gt;
You can create as many assessments as you like, and you can create more than one assessment to display for a given score.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:26--&amp;gt;&lt;br /&gt;
It is important to note that if you use assessments, you must ensure that you have not chosen to autoload the URL at the end of the survey in the general survey setup, because the assessments only show on the final &amp;quot;completed&amp;quot; page after submitting a survey.  This is located in the &amp;quot;Edit survey text elements and settings&amp;quot;, under the &amp;quot;Presentation &amp;amp; navigation&amp;quot; settings, and finally a toggle button called &amp;quot;Automatically load URL when survey completes:&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==Assessment placeholders== &amp;lt;!--T:27--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:28--&amp;gt;&lt;br /&gt;
When using assessments the following placeholders are available:&lt;br /&gt;
* {PERC}: Displays the score of the current group. Only available at assessment message&lt;br /&gt;
* {TOTAL}: Displays the total score. Only available at assessment message&lt;br /&gt;
* {ASSESSMENT_CURRENT_TOTAL}{{NewIn|1.86}}: This placeholder can be used within a survey to display the current total score. Keep in mind that the score is only updated when clicking &amp;quot;next&amp;quot; so this is useless in an all-in-one survey. For now, you must create at least one assessment rule for the placeholder to work.&lt;br /&gt;
&lt;br /&gt;
=Tips &amp;amp; tricks= &amp;lt;!--T:29--&amp;gt;&lt;br /&gt;
* If you &#039;&#039;&#039;only want to use the {ASSESSMENT_CURRENT_TOTAL} placeholder&#039;&#039;&#039; {{NewIn|1.86}} within a survey without showing an assessment message at the end of the survey you can:&lt;br /&gt;
** Use an [[Creating_a_new_survey#General|end URL]] and [[Creating_a_new_survey#Presentation_.26_navigation| activate the auto load end URL setting]] for your survey. Then the user will be directly forwarded to the given URL.&lt;br /&gt;
&lt;br /&gt;
=Video tutorials= &amp;lt;!--T:30--&amp;gt;&lt;br /&gt;
*[http://www.youtube.com/watch?v=Xe1ipbkJdIw Assessments &amp;amp; Conditions]&lt;br /&gt;
&amp;lt;/translate&amp;gt;&lt;/div&gt;</summary>
		<author><name>LimeAJ</name></author>
	</entry>
	<entry>
		<id>https://www.limesurvey.org/manual/index.php?title=Assessments&amp;diff=73645</id>
		<title>Assessments</title>
		<link rel="alternate" type="text/html" href="https://www.limesurvey.org/manual/index.php?title=Assessments&amp;diff=73645"/>
		<updated>2017-05-29T17:38:23Z</updated>

		<summary type="html">&lt;p&gt;LimeAJ: Value of button is On/Off, instead of Yes/No.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;languages /&amp;gt; &amp;lt;translate&amp;gt;&lt;br /&gt;
&amp;lt;!--T:1--&amp;gt;&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:2--&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;simplebox&amp;quot;&amp;gt;Note: Starting in Version 1.92, you can create more sophisticated assessments and reports using [[Expression Manager|Expression Manager]].  It lets you access all variable types, and easily generate tailored  reports at any point in the survey (not just the end).  Using the new Equation question type, you can have LimeSurvey automatically save your assessment calculate and/or report to the database&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=General= &amp;lt;!--T:3--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:4--&amp;gt;&lt;br /&gt;
LimeSurvey has the ability to create &amp;quot;assessments&amp;quot; on your survey - even for multilingual surveys. Assessments are rules which evaluate the responses to a survey immediately after it is submitted, and then display text blocks to the participant based on that evaluation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:5--&amp;gt;&lt;br /&gt;
An english sample survey demonstrating the use of assessments at LimeSurvey is available for download. You can import this survey at your LimeSurvey system for testing (&amp;quot;import&amp;quot; tab at survey creation page): [[File:Limesurvey_sample_survey_Assessment.lss]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:6--&amp;gt;&lt;br /&gt;
As an example, consider the following: You have two questions in your survey, the first question asks if the user smokes: &amp;quot;Do you smoke?&amp;quot;. The question has 3 possible answers, &amp;quot;Yes more than 10 per day&amp;quot; with an answer code of &amp;quot;10&amp;quot;, &amp;quot;Yes, but less than 10 per day&amp;quot; with an answer code of &amp;quot;5&amp;quot; and &amp;quot;No, I don&#039;t smoke at all&amp;quot; with an answer code of &amp;quot;1&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:7--&amp;gt;&lt;br /&gt;
The second question &amp;quot;Do you exercise?&amp;quot; has three possible answers; &amp;quot;Yes, I exercise for at least half an hour three times a week&amp;quot; with a value of &amp;quot;1&amp;quot;, &amp;quot;Yes, I exercise every now and then&amp;quot; with a value of &amp;quot;5&amp;quot; and &amp;quot;No, I don&#039;t ever do any exercise&amp;quot; with an answer code/value of &amp;quot;10&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:8--&amp;gt;&lt;br /&gt;
If we were to add the totals of the values for each possible answer at the end of the survey, we&#039;d have a good indication of the general health of the respondent. Someone who smokes and doesn&#039;t ever do any exercise will have scored 10 in each of their answers, giving a sum of 20 when we add the values together. Someone who doesn&#039;t smoke and exercises regularly will have scored 1 in each of the answers with a total of 2 when we add the values together.&lt;br /&gt;
&lt;br /&gt;
=How to use= &amp;lt;!--T:9--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Activate assessments== &amp;lt;!--T:10--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:11--&amp;gt;&lt;br /&gt;
To be able to see and edit assessments for answers visit the survey settings and change the setting &#039;&#039;&#039;Use assessments?&#039;&#039;&#039; in the &#039;&#039;&#039;[[Creating_a_new_survey#Notification_.26_data_management|Notification &amp;amp; data management]]&#039;&#039;&#039; tab to &#039;On&#039;. After that you will be presented with additional fields when editing answers.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:12--&amp;gt;&lt;br /&gt;
In [[Label sets|label sets]] these fields are always visible.&lt;br /&gt;
&lt;br /&gt;
==Set assessment values for each answer/label== &amp;lt;!--T:13--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:31--&amp;gt;&lt;br /&gt;
[[File:Assesment_value_set.png|thumb|Set the assessment value]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:14--&amp;gt;&lt;br /&gt;
The assessments tool allows you to set some rules based on the summed assessment values of the questions in the survey, either for the total survey, or for each group within the survey. If you now edit an answer of a question you will see an additional field right beside each code field where you can set an assessment value for this answer.&lt;br /&gt;
&lt;br /&gt;
==How question types are evaluated== &amp;lt;!--T:16--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:17--&amp;gt;&lt;br /&gt;
There are certain [[question types]] which will not be assessed or will be assessed in a special way. Most question types that are not being assessed are convenience question types and can be replaced with a assessable question type - for example a 5 point choice can always be replaced with a simple radio single select question type.&lt;br /&gt;
&lt;br /&gt;
===Question types being assessed=== &amp;lt;!--T:18--&amp;gt;&lt;br /&gt;
*Array (Flexible labels) dual scale&lt;br /&gt;
*Array (Flexible labels)&lt;br /&gt;
*Array (Flexible labels) by column&lt;br /&gt;
*List (Flexible labels) (Dropdown)&lt;br /&gt;
*List (Flexible labels) (Radio)&lt;br /&gt;
*List (Dropdown)&lt;br /&gt;
*List (Radio)&lt;br /&gt;
*List with comment&lt;br /&gt;
*Multiple options&lt;br /&gt;
*Multiple options with comments&lt;br /&gt;
&lt;br /&gt;
===Question types not being assessed by values set in answers or label set=== &amp;lt;!--T:19--&amp;gt;&lt;br /&gt;
*Array (Multi Flexible) (Numbers)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:20--&amp;gt;&lt;br /&gt;
With this question type the chosen values in the select boxes will used as the value for assessment.&lt;br /&gt;
&lt;br /&gt;
===Question types not being assessed=== &amp;lt;!--T:21--&amp;gt;&lt;br /&gt;
* 5 point choice&lt;br /&gt;
* Array (5 point choice)&lt;br /&gt;
* Array (10 point choice)&lt;br /&gt;
* Array (Increase, Same, Decrease)&lt;br /&gt;
* Array (Multi flexible) (Text)&lt;br /&gt;
* Array (Yes/No/Uncertain)&lt;br /&gt;
* Boilerplate question&lt;br /&gt;
* Date&lt;br /&gt;
* Gender&lt;br /&gt;
* Huge free text&lt;br /&gt;
* Language switch&lt;br /&gt;
* Long free text&lt;br /&gt;
* Multiple numerical input&lt;br /&gt;
* Numerical input&lt;br /&gt;
* Ranking&lt;br /&gt;
* Short free text&lt;br /&gt;
* Yes/No&lt;br /&gt;
&lt;br /&gt;
==Define assessment rules== &amp;lt;!--T:22--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:23--&amp;gt;&lt;br /&gt;
Now you want to define rules on the assessment values - to do this click the assessment icon [[File:assessments.png]] in one of the menus on the survey administration toolbar. From this screen you can view, edit or delete existing assessments or create new assessments.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:24--&amp;gt;&lt;br /&gt;
In the &amp;quot;Add/Edit&amp;quot; box you can choose the following:&lt;br /&gt;
*Scope: The scope of the assessment. Choose either &amp;quot;Total&amp;quot; which will create an assessment based on the sum of all the answers in the entire survey, or &amp;quot;Group&amp;quot; which will create an assessment based on the sum of all the answers in a group (chosen in the next row)&lt;br /&gt;
*Group: If the scope of this assessment is for the current &amp;quot;Group&amp;quot;, this is where you choose which group to assess.&lt;br /&gt;
*Minimum: The minimum &amp;quot;sum&amp;quot; of answers to which this assessment will apply&lt;br /&gt;
*Maximum: The maximum &amp;quot;sum&amp;quot; of answers to which this assessment will apply&lt;br /&gt;
*Heading: The heading of the assessment which will display if this assessment is shown&lt;br /&gt;
*Message: The actual message for this assessment. Inside the message you can use the tags {PERC} or {TOTAL} to show the related score in that particular message.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:25--&amp;gt;&lt;br /&gt;
You can create as many assessments as you like, and you can create more than one assessment to display for a given score.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:26--&amp;gt;&lt;br /&gt;
It is important to note that if you use assessments, you must ensure that you have not chosen to autoload the URL at the end of the survey in the general survey setup, because the assessments only show on the final &amp;quot;completed&amp;quot; page after submitting a survey.&lt;br /&gt;
&lt;br /&gt;
==Assessment placeholders== &amp;lt;!--T:27--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:28--&amp;gt;&lt;br /&gt;
When using assessments the following placeholders are available:&lt;br /&gt;
* {PERC}: Displays the score of the current group. Only available at assessment message&lt;br /&gt;
* {TOTAL}: Displays the total score. Only available at assessment message&lt;br /&gt;
* {ASSESSMENT_CURRENT_TOTAL}{{NewIn|1.86}}: This placeholder can be used within a survey to display the current total score. Keep in mind that the score is only updated when clicking &amp;quot;next&amp;quot; so this is useless in an all-in-one survey. For now, you must create at least one assessment rule for the placeholder to work.&lt;br /&gt;
&lt;br /&gt;
=Tips &amp;amp; tricks= &amp;lt;!--T:29--&amp;gt;&lt;br /&gt;
* If you &#039;&#039;&#039;only want to use the {ASSESSMENT_CURRENT_TOTAL} placeholder&#039;&#039;&#039; {{NewIn|1.86}} within a survey without showing an assessment message at the end of the survey you can:&lt;br /&gt;
** Use an [[Creating_a_new_survey#General|end URL]] and [[Creating_a_new_survey#Presentation_.26_navigation| activate the auto load end URL setting]] for your survey. Then the user will be directly forwarded to the given URL.&lt;br /&gt;
&lt;br /&gt;
=Video tutorials= &amp;lt;!--T:30--&amp;gt;&lt;br /&gt;
*[http://www.youtube.com/watch?v=Xe1ipbkJdIw Assessments &amp;amp; Conditions]&lt;br /&gt;
&amp;lt;/translate&amp;gt;&lt;/div&gt;</summary>
		<author><name>LimeAJ</name></author>
	</entry>
	<entry>
		<id>https://www.limesurvey.org/manual/index.php?title=Questions_-_introduction&amp;diff=72962</id>
		<title>Questions - introduction</title>
		<link rel="alternate" type="text/html" href="https://www.limesurvey.org/manual/index.php?title=Questions_-_introduction&amp;diff=72962"/>
		<updated>2017-03-30T13:24:14Z</updated>

		<summary type="html">&lt;p&gt;LimeAJ: by using CSS --&amp;gt; with CSS&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;languages /&amp;gt; &amp;lt;translate&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:1--&amp;gt;&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
=Introduction= &amp;lt;!--T:2--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:3--&amp;gt;&lt;br /&gt;
Once you have [[Creating a question group|created your groups]], you can start adding questions within each group. Create a new question by clicking on the add icon [[File:add.png]] on the right hand side of the &amp;quot;Group&amp;quot; menu bar.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:4--&amp;gt;&lt;br /&gt;
When adding a question, you will be asked for a &amp;quot;Question Code&amp;quot;, the &amp;quot;Question&amp;quot;, &amp;quot;Help&amp;quot; and a &amp;quot;(Question Types|question type)&amp;quot;. All new questions are assigned to the Group you were viewing when you clicked &amp;quot;Add Question&amp;quot;, however you can change the group the question belongs to at a later point.&lt;br /&gt;
&lt;br /&gt;
=Field descriptions= &amp;lt;!--T:5--&amp;gt;&lt;br /&gt;
*&#039;&#039;&#039;Question code:&#039;&#039;&#039; Your ID, or number or code for the question. This field is only for quick identification for a question in export or for evaluation. Try to be consistent with your coding in this field. Planning makes your evaluation a lot easier at a later time. This field is normally not displayed to people taking the survey.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:6--&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;simplebox&amp;quot;&amp;gt;Note: The question Code must be unique across the same survey, must start with a letter, and only contain letters and numbers.  If you ever tried to export your data to SPSS or R, you discovered that the qcode becomes the value label, so you have to make code unique.  For the time-being, LimeSurvey will support legacy code values, but the [[Show Logic File|Show Logic File]] button will color-code such questions so that you know you should change their names.&amp;lt;/div&amp;gt;&lt;br /&gt;
*&#039;&#039;&#039;Question:&#039;&#039;&#039; This is the actual question being asked. There is no real limit to the length of the question here, however if you want to explain how to fill out the question, leave that for the &amp;quot;Help&amp;quot; field. HTML-code can be used, e.g., for including images:&amp;lt;br /&amp;gt;&amp;lt;nowiki&amp;gt;&amp;lt;img src=&amp;quot;http://www.yourdomain.com/yourpics/pic.jpg&amp;quot;&amp;gt;&amp;lt;/nowiki&amp;gt;. The HTML WYSIWYG editor usually helps with the most important tasks, like including images, etc.&lt;br /&gt;
*&#039;&#039;&#039;Help:&#039;&#039;&#039; This is an optional field. It is useful if a question needs some explanation, or you want to explain how it should be answered. When you put text in this field, a &amp;quot;Question Mark&amp;quot; icon appears on the survey entry screens with the help text right beside.&lt;br /&gt;
*&#039;&#039;&#039;Question type:&#039;&#039;&#039; This determines the type of response the survey allows. View the [[Question types]] section for a description of the various options available.&lt;br /&gt;
*&#039;&#039;&#039;Validation:&#039;&#039;&#039; This feature is available on all free text type or numeric questions. You can use standard [[Using regular expressions|Regular Expressions]] in this field to validate the responses to the question, and if the responses don&#039;t validate against this expression, the user will be prompted to try again before they can progress.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:7--&amp;gt;&lt;br /&gt;
*&#039;&#039;&#039;Other?:&#039;&#039;&#039; Depending upon your chosen &#039;question type&#039; this option may appear. It allows you to specify that an &amp;quot;other&amp;quot; option be presented in some of the list question types.&lt;br /&gt;
*&#039;&#039;&#039;Mandatory?:&#039;&#039;&#039; For all question types this setting allows you to require users to answer the question, before they can move on to the next question. For ranking question this means all items have to be ranked.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:9--&amp;gt;&lt;br /&gt;
*&#039;&#039;&#039;Relevance&#039;&#039;&#039;:  This is the Boolean equation that specifies the conditions for this question.  If it evaluates to true, the question is show; otherwise it is hidden and since it is irrelevant, data for that question is NULLed in the database.  Details about how to use Relevance can be found on the [[Expression Manager|Expression Manager]] pages.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:8--&amp;gt;&lt;br /&gt;
*&#039;&#039;&#039;Show advanced question settings:&#039;&#039;&#039; The advanced question settings are different for each question type. Please consult the documentation for your particular [[Question types|question type]]&lt;br /&gt;
&lt;br /&gt;
=Importing a question= &amp;lt;!--T:10--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:11--&amp;gt;&lt;br /&gt;
At the bottom of the New Question Form you will find a file selection box to import a question file. Here you can import any question file (*.lsq or *.csv (old format)) you previously exported - for example this is useful if you want to reuse a question from another survey.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:12--&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;simplebox&amp;quot;&amp;gt;Important: If you import a question there will always be a new question created. The original question will not be overwritten. If you want to copy a question inside the same survey it is easier to select the existing question and then use the &amp;quot;Copy current question&amp;quot; button.&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Information from tokens table= &amp;lt;!--T:13--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:14--&amp;gt;&lt;br /&gt;
You can insert information/text from the tokens table into your question so that it can show context related information. For LimeSurvey to do this, the survey needs to be set as NOT Anonymous (ie: tracked), and it needs to have a tokens table.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;The fields available for this are:&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:15--&amp;gt;&lt;br /&gt;
{|&lt;br /&gt;
|{TOKEN:FIRSTNAME}||inserts the value from the &amp;quot;firstname&amp;quot; field in the tokens table&lt;br /&gt;
|-&lt;br /&gt;
|{TOKEN:LASTNAME}||inserts the value from the &amp;quot;lastname&amp;quot; field in the tokens table&lt;br /&gt;
|-&lt;br /&gt;
|{TOKEN:EMAIL}||inserts the value from the &amp;quot;email&amp;quot; field in the tokens table&lt;br /&gt;
|-&lt;br /&gt;
|{TOKEN:ATTRIBUTE_1}||inserts the value from the &amp;quot;attribute_1&amp;quot; field in the tokens table&lt;br /&gt;
|-&lt;br /&gt;
|{TOKEN:ATTRIBUTE_2}||inserts the value from the &amp;quot;attribute_2&amp;quot; field in the tokens table&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:16--&amp;gt;&lt;br /&gt;
To use this functionality you must type the field text into your question exactly as listed above. &lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:17--&amp;gt;&lt;br /&gt;
Hello {TOKEN:FIRSTNAME}. We sent an email to you using this address {TOKEN:EMAIL}. Is this correct?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:18--&amp;gt;&lt;br /&gt;
Another example with more customisation, but using JavaScript (please see [[Optional settings |Optional settings]] on how to allow JavaScript when setting up questions and why it&#039;s not always a good idea. To use JavaScript you will need to deactivate the XSS filter in the [[Global settings]]):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:21--&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;Hello {TOKEN:FIRSTNAME}. We sent an email to you using this address {TOKEN:EMAIL}. Is this correct?&lt;br /&gt;
What do you as a {TOKEN:ATTRIBUTE_1} think about your&lt;br /&gt;
&amp;lt;script type=&amp;quot;text/javascript&amp;quot; language=&amp;quot;Javascript&amp;quot;&amp;gt;;&lt;br /&gt;
   var job=&#039;{TOKEN:ATTRIBUTE_1}&#039;;&lt;br /&gt;
   if (job==&#039;worker&#039;) {&lt;br /&gt;
      document.write (&#039;bosses&#039;)&lt;br /&gt;
   } else {&lt;br /&gt;
      document.write(&#039;workers&#039;)&lt;br /&gt;
   }&lt;br /&gt;
&amp;lt;/script&amp;gt;&lt;br /&gt;
?&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:22--&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;simplebox&amp;quot;&amp;gt;Starting in Version 1.92, you can use [[Expression Manager|Expression Manager]] to do such tailoring without needing JavaScript.  The equivalent in Version 1.92 is the following:&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:23--&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;What do you as a {TOKEN:ATTRIBUTE_1} think about your {if(TOKEN:ATTRIBUTE_1==&#039;worker&#039;,&#039;bosses&#039;,&#039;workers&#039;)}?&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Information from previous answers= &amp;lt;!--T:24--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:25--&amp;gt;&lt;br /&gt;
There is currently also the capacity to insert the answer of previous questions into the text of an answer:&lt;br /&gt;
*You can refer to answers on the same page, and even dynamically update tailored messages as responses change on the page.&lt;br /&gt;
*You can use question code naming - for more details, see the [[Expression Manager|Expression Manager]] documentation&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:27--&amp;gt;&lt;br /&gt;
A wizard has been integrated in the Wysiwyg HTML editor (FCKeditor), so that you can easilly insert previous question/answer codes: this plugin is called the LimeReplacementFields. In order to use this feature, in the FCKeditor, click on the &amp;quot;lime between brackets&amp;quot; icon, and select a question from the select box. Only answers from previous pages are displayed.&lt;br /&gt;
&lt;br /&gt;
[[File:Editor_replacementfields_button.png]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:28--&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;simplebox&amp;quot;&amp;gt;LimeReplacementFields notice: when you want to delete a reference to a {name} tag, please select all chars from the openning bracket to the closing bracket and press delete: DO NOT erase it char by char with the Delete or Backspace key otherwise the field will appear again.&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Styling Questions= &amp;lt;!--T:29--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:30--&amp;gt;&lt;br /&gt;
It is possible to generally edit the question layout/design with CSS using [[The template editor|the template editor]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/translate&amp;gt;&lt;/div&gt;</summary>
		<author><name>LimeAJ</name></author>
	</entry>
	<entry>
		<id>https://www.limesurvey.org/manual/index.php?title=Questions_-_introduction&amp;diff=72961</id>
		<title>Questions - introduction</title>
		<link rel="alternate" type="text/html" href="https://www.limesurvey.org/manual/index.php?title=Questions_-_introduction&amp;diff=72961"/>
		<updated>2017-03-30T13:20:45Z</updated>

		<summary type="html">&lt;p&gt;LimeAJ: grammar correction&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;languages /&amp;gt; &amp;lt;translate&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:1--&amp;gt;&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
=Introduction= &amp;lt;!--T:2--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:3--&amp;gt;&lt;br /&gt;
Once you have [[Creating a question group|created your groups]], you can start adding questions within each group. Create a new question by clicking on the add icon [[File:add.png]] on the right hand side of the &amp;quot;Group&amp;quot; menu bar.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:4--&amp;gt;&lt;br /&gt;
When adding a question, you will be asked for a &amp;quot;Question Code&amp;quot;, the &amp;quot;Question&amp;quot;, &amp;quot;Help&amp;quot; and a &amp;quot;(Question Types|question type)&amp;quot;. All new questions are assigned to the Group you were viewing when you clicked &amp;quot;Add Question&amp;quot;, however you can change the group the question belongs to at a later point.&lt;br /&gt;
&lt;br /&gt;
=Field descriptions= &amp;lt;!--T:5--&amp;gt;&lt;br /&gt;
*&#039;&#039;&#039;Question code:&#039;&#039;&#039; Your ID, or number or code for the question. This field is only for quick identification for a question in export or for evaluation. Try to be consistent with your coding in this field. Planning makes your evaluation a lot easier at a later time. This field is normally not displayed to people taking the survey.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:6--&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;simplebox&amp;quot;&amp;gt;Note: The question Code must be unique across the same survey, must start with a letter, and only contain letters and numbers.  If you ever tried to export your data to SPSS or R, you discovered that the qcode becomes the value label, so you have to make code unique.  For the time-being, LimeSurvey will support legacy code values, but the [[Show Logic File|Show Logic File]] button will color-code such questions so that you know you should change their names.&amp;lt;/div&amp;gt;&lt;br /&gt;
*&#039;&#039;&#039;Question:&#039;&#039;&#039; This is the actual question being asked. There is no real limit to the length of the question here, however if you want to explain how to fill out the question, leave that for the &amp;quot;Help&amp;quot; field. HTML-code can be used, e.g., for including images:&amp;lt;br /&amp;gt;&amp;lt;nowiki&amp;gt;&amp;lt;img src=&amp;quot;http://www.yourdomain.com/yourpics/pic.jpg&amp;quot;&amp;gt;&amp;lt;/nowiki&amp;gt;. The HTML WYSIWYG editor usually helps with the most important tasks, like including images, etc.&lt;br /&gt;
*&#039;&#039;&#039;Help:&#039;&#039;&#039; This is an optional field. It is useful if a question needs some explanation, or you want to explain how it should be answered. When you put text in this field, a &amp;quot;Question Mark&amp;quot; icon appears on the survey entry screens with the help text right beside.&lt;br /&gt;
*&#039;&#039;&#039;Question type:&#039;&#039;&#039; This determines the type of response the survey allows. View the [[Question types]] section for a description of the various options available.&lt;br /&gt;
*&#039;&#039;&#039;Validation:&#039;&#039;&#039; This feature is available on all free text type or numeric questions. You can use standard [[Using regular expressions|Regular Expressions]] in this field to validate the responses to the question, and if the responses don&#039;t validate against this expression, the user will be prompted to try again before they can progress.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:7--&amp;gt;&lt;br /&gt;
*&#039;&#039;&#039;Other?:&#039;&#039;&#039; Depending upon your chosen &#039;question type&#039; this option may appear. It allows you to specify that an &amp;quot;other&amp;quot; option be presented in some of the list question types.&lt;br /&gt;
*&#039;&#039;&#039;Mandatory?:&#039;&#039;&#039; For all question types this setting allows you to require users to answer the question, before they can move on to the next question. For ranking question this means all items have to be ranked.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:9--&amp;gt;&lt;br /&gt;
*&#039;&#039;&#039;Relevance&#039;&#039;&#039;:  This is the Boolean equation that specifies the conditions for this question.  If it evaluates to true, the question is show; otherwise it is hidden and since it is irrelevant, data for that question is NULLed in the database.  Details about how to use Relevance can be found on the [[Expression Manager|Expression Manager]] pages.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:8--&amp;gt;&lt;br /&gt;
*&#039;&#039;&#039;Show advanced question settings:&#039;&#039;&#039; The advanced question settings are different for each question type. Please consult the documentation for your particular [[Question types|question type]]&lt;br /&gt;
&lt;br /&gt;
=Importing a question= &amp;lt;!--T:10--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:11--&amp;gt;&lt;br /&gt;
At the bottom of the New Question Form you will find a file selection box to import a question file. Here you can import any question file (*.lsq or *.csv (old format)) you previously exported - for example this is useful if you want to reuse a question from another survey.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:12--&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;simplebox&amp;quot;&amp;gt;Important: If you import a question there will always be a new question created. The original question will not be overwritten. If you want to copy a question inside the same survey it is easier to select the existing question and then use the &amp;quot;Copy current question&amp;quot; button.&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Information from tokens table= &amp;lt;!--T:13--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:14--&amp;gt;&lt;br /&gt;
You can insert information/text from the tokens table into your question so that it can show context related information. For LimeSurvey to do this, the survey needs to be set as NOT Anonymous (ie: tracked), and it needs to have a tokens table.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;The fields available for this are:&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:15--&amp;gt;&lt;br /&gt;
{|&lt;br /&gt;
|{TOKEN:FIRSTNAME}||inserts the value from the &amp;quot;firstname&amp;quot; field in the tokens table&lt;br /&gt;
|-&lt;br /&gt;
|{TOKEN:LASTNAME}||inserts the value from the &amp;quot;lastname&amp;quot; field in the tokens table&lt;br /&gt;
|-&lt;br /&gt;
|{TOKEN:EMAIL}||inserts the value from the &amp;quot;email&amp;quot; field in the tokens table&lt;br /&gt;
|-&lt;br /&gt;
|{TOKEN:ATTRIBUTE_1}||inserts the value from the &amp;quot;attribute_1&amp;quot; field in the tokens table&lt;br /&gt;
|-&lt;br /&gt;
|{TOKEN:ATTRIBUTE_2}||inserts the value from the &amp;quot;attribute_2&amp;quot; field in the tokens table&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:16--&amp;gt;&lt;br /&gt;
To use this functionality you must type the field text into your question exactly as listed above. &lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:17--&amp;gt;&lt;br /&gt;
Hello {TOKEN:FIRSTNAME}. We sent an email to you using this address {TOKEN:EMAIL}. Is this correct?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:18--&amp;gt;&lt;br /&gt;
Another example with more customisation, but using JavaScript (please see [[Optional settings |Optional settings]] on how to allow JavaScript when setting up questions and why it&#039;s not always a good idea. To use JavaScript you will need to deactivate the XSS filter in the [[Global settings]]):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:21--&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;Hello {TOKEN:FIRSTNAME}. We sent an email to you using this address {TOKEN:EMAIL}. Is this correct?&lt;br /&gt;
What do you as a {TOKEN:ATTRIBUTE_1} think about your&lt;br /&gt;
&amp;lt;script type=&amp;quot;text/javascript&amp;quot; language=&amp;quot;Javascript&amp;quot;&amp;gt;;&lt;br /&gt;
   var job=&#039;{TOKEN:ATTRIBUTE_1}&#039;;&lt;br /&gt;
   if (job==&#039;worker&#039;) {&lt;br /&gt;
      document.write (&#039;bosses&#039;)&lt;br /&gt;
   } else {&lt;br /&gt;
      document.write(&#039;workers&#039;)&lt;br /&gt;
   }&lt;br /&gt;
&amp;lt;/script&amp;gt;&lt;br /&gt;
?&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:22--&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;simplebox&amp;quot;&amp;gt;Starting in Version 1.92, you can use [[Expression Manager|Expression Manager]] to do such tailoring without needing JavaScript.  The equivalent in Version 1.92 is the following:&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:23--&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;What do you as a {TOKEN:ATTRIBUTE_1} think about your {if(TOKEN:ATTRIBUTE_1==&#039;worker&#039;,&#039;bosses&#039;,&#039;workers&#039;)}?&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Information from previous answers= &amp;lt;!--T:24--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:25--&amp;gt;&lt;br /&gt;
There is currently also the capacity to insert the answer of previous questions into the text of an answer:&lt;br /&gt;
*You can refer to answers on the same page, and even dynamically update tailored messages as responses change on the page.&lt;br /&gt;
*You can use question code naming - for more details, see the [[Expression Manager|Expression Manager]] documentation&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:27--&amp;gt;&lt;br /&gt;
A wizard has been integrated in the Wysiwyg HTML editor (FCKeditor), so that you can easilly insert previous question/answer codes: this plugin is called the LimeReplacementFields. In order to use this feature, in the FCKeditor, click on the &amp;quot;lime between brackets&amp;quot; icon, and select a question from the select box. Only answers from previous pages are displayed.&lt;br /&gt;
&lt;br /&gt;
[[File:Editor_replacementfields_button.png]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:28--&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;simplebox&amp;quot;&amp;gt;LimeReplacementFields notice: when you want to delete a reference to a {name} tag, please select all chars from the openning bracket to the closing bracket and press delete: DO NOT erase it char by char with the Delete or Backspace key otherwise the field will appear again.&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Styling Questions= &amp;lt;!--T:29--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:30--&amp;gt;&lt;br /&gt;
It is possible to generally edit the question layout/design by using CSS using [[The template editor|the template editor]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/translate&amp;gt;&lt;/div&gt;</summary>
		<author><name>LimeAJ</name></author>
	</entry>
	<entry>
		<id>https://www.limesurvey.org/manual/index.php?title=Questions_-_introduction&amp;diff=72960</id>
		<title>Questions - introduction</title>
		<link rel="alternate" type="text/html" href="https://www.limesurvey.org/manual/index.php?title=Questions_-_introduction&amp;diff=72960"/>
		<updated>2017-03-30T13:20:17Z</updated>

		<summary type="html">&lt;p&gt;LimeAJ: grammar correction&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;languages /&amp;gt; &amp;lt;translate&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:1--&amp;gt;&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
=Introduction= &amp;lt;!--T:2--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:3--&amp;gt;&lt;br /&gt;
Once you have [[Creating a question group|created your groups]], you can start adding questions within each group. Create a new question by clicking on the add icon [[File:add.png]] on the right hand side of the &amp;quot;Group&amp;quot; menu bar.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:4--&amp;gt;&lt;br /&gt;
When adding a question, you will be asked for a &amp;quot;Question Code&amp;quot;, the &amp;quot;Question&amp;quot;, &amp;quot;Help&amp;quot; and a &amp;quot;(Question Types|question type)&amp;quot;. All new questions are assigned to the Group you were viewing when you clicked &amp;quot;Add Question&amp;quot;, however you can change the group the question belongs too at a later point.&lt;br /&gt;
&lt;br /&gt;
=Field descriptions= &amp;lt;!--T:5--&amp;gt;&lt;br /&gt;
*&#039;&#039;&#039;Question code:&#039;&#039;&#039; Your ID, or number or code for the question. This field is only for quick identification for a question in export or for evaluation. Try to be consistent with your coding in this field. Planning makes your evaluation a lot easier at a later time. This field is normally not displayed to people taking the survey.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:6--&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;simplebox&amp;quot;&amp;gt;Note: The question Code must be unique across the same survey, must start with a letter, and only contain letters and numbers.  If you ever tried to export your data to SPSS or R, you discovered that the qcode becomes the value label, so you have to make code unique.  For the time-being, LimeSurvey will support legacy code values, but the [[Show Logic File|Show Logic File]] button will color-code such questions so that you know you should change their names.&amp;lt;/div&amp;gt;&lt;br /&gt;
*&#039;&#039;&#039;Question:&#039;&#039;&#039; This is the actual question being asked. There is no real limit to the length of the question here, however if you want to explain how to fill out the question, leave that for the &amp;quot;Help&amp;quot; field. HTML-code can be used, e.g., for including images:&amp;lt;br /&amp;gt;&amp;lt;nowiki&amp;gt;&amp;lt;img src=&amp;quot;http://www.yourdomain.com/yourpics/pic.jpg&amp;quot;&amp;gt;&amp;lt;/nowiki&amp;gt;. The HTML WYSIWYG editor usually helps with the most important tasks, like including images, etc.&lt;br /&gt;
*&#039;&#039;&#039;Help:&#039;&#039;&#039; This is an optional field. It is useful if a question needs some explanation, or you want to explain how it should be answered. When you put text in this field, a &amp;quot;Question Mark&amp;quot; icon appears on the survey entry screens with the help text right beside.&lt;br /&gt;
*&#039;&#039;&#039;Question type:&#039;&#039;&#039; This determines the type of response the survey allows. View the [[Question types]] section for a description of the various options available.&lt;br /&gt;
*&#039;&#039;&#039;Validation:&#039;&#039;&#039; This feature is available on all free text type or numeric questions. You can use standard [[Using regular expressions|Regular Expressions]] in this field to validate the responses to the question, and if the responses don&#039;t validate against this expression, the user will be prompted to try again before they can progress.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:7--&amp;gt;&lt;br /&gt;
*&#039;&#039;&#039;Other?:&#039;&#039;&#039; Depending upon your chosen &#039;question type&#039; this option may appear. It allows you to specify that an &amp;quot;other&amp;quot; option be presented in some of the list question types.&lt;br /&gt;
*&#039;&#039;&#039;Mandatory?:&#039;&#039;&#039; For all question types this setting allows you to require users to answer the question, before they can move on to the next question. For ranking question this means all items have to be ranked.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:9--&amp;gt;&lt;br /&gt;
*&#039;&#039;&#039;Relevance&#039;&#039;&#039;:  This is the Boolean equation that specifies the conditions for this question.  If it evaluates to true, the question is show; otherwise it is hidden and since it is irrelevant, data for that question is NULLed in the database.  Details about how to use Relevance can be found on the [[Expression Manager|Expression Manager]] pages.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:8--&amp;gt;&lt;br /&gt;
*&#039;&#039;&#039;Show advanced question settings:&#039;&#039;&#039; The advanced question settings are different for each question type. Please consult the documentation for your particular [[Question types|question type]]&lt;br /&gt;
&lt;br /&gt;
=Importing a question= &amp;lt;!--T:10--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:11--&amp;gt;&lt;br /&gt;
At the bottom of the New Question Form you will find a file selection box to import a question file. Here you can import any question file (*.lsq or *.csv (old format)) you previously exported - for example this is useful if you want to reuse a question from another survey.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:12--&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;simplebox&amp;quot;&amp;gt;Important: If you import a question there will always be a new question created. The original question will not be overwritten. If you want to copy a question inside the same survey it is easier to select the existing question and then use the &amp;quot;Copy current question&amp;quot; button.&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Information from tokens table= &amp;lt;!--T:13--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:14--&amp;gt;&lt;br /&gt;
You can insert information/text from the tokens table into your question so that it can show context related information. For LimeSurvey to do this, the survey needs to be set as NOT Anonymous (ie: tracked), and it needs to have a tokens table.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;The fields available for this are:&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:15--&amp;gt;&lt;br /&gt;
{|&lt;br /&gt;
|{TOKEN:FIRSTNAME}||inserts the value from the &amp;quot;firstname&amp;quot; field in the tokens table&lt;br /&gt;
|-&lt;br /&gt;
|{TOKEN:LASTNAME}||inserts the value from the &amp;quot;lastname&amp;quot; field in the tokens table&lt;br /&gt;
|-&lt;br /&gt;
|{TOKEN:EMAIL}||inserts the value from the &amp;quot;email&amp;quot; field in the tokens table&lt;br /&gt;
|-&lt;br /&gt;
|{TOKEN:ATTRIBUTE_1}||inserts the value from the &amp;quot;attribute_1&amp;quot; field in the tokens table&lt;br /&gt;
|-&lt;br /&gt;
|{TOKEN:ATTRIBUTE_2}||inserts the value from the &amp;quot;attribute_2&amp;quot; field in the tokens table&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:16--&amp;gt;&lt;br /&gt;
To use this functionality you must type the field text into your question exactly as listed above. &lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:17--&amp;gt;&lt;br /&gt;
Hello {TOKEN:FIRSTNAME}. We sent an email to you using this address {TOKEN:EMAIL}. Is this correct?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:18--&amp;gt;&lt;br /&gt;
Another example with more customisation, but using JavaScript (please see [[Optional settings |Optional settings]] on how to allow JavaScript when setting up questions and why it&#039;s not always a good idea. To use JavaScript you will need to deactivate the XSS filter in the [[Global settings]]):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:21--&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;Hello {TOKEN:FIRSTNAME}. We sent an email to you using this address {TOKEN:EMAIL}. Is this correct?&lt;br /&gt;
What do you as a {TOKEN:ATTRIBUTE_1} think about your&lt;br /&gt;
&amp;lt;script type=&amp;quot;text/javascript&amp;quot; language=&amp;quot;Javascript&amp;quot;&amp;gt;;&lt;br /&gt;
   var job=&#039;{TOKEN:ATTRIBUTE_1}&#039;;&lt;br /&gt;
   if (job==&#039;worker&#039;) {&lt;br /&gt;
      document.write (&#039;bosses&#039;)&lt;br /&gt;
   } else {&lt;br /&gt;
      document.write(&#039;workers&#039;)&lt;br /&gt;
   }&lt;br /&gt;
&amp;lt;/script&amp;gt;&lt;br /&gt;
?&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:22--&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;simplebox&amp;quot;&amp;gt;Starting in Version 1.92, you can use [[Expression Manager|Expression Manager]] to do such tailoring without needing JavaScript.  The equivalent in Version 1.92 is the following:&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:23--&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;What do you as a {TOKEN:ATTRIBUTE_1} think about your {if(TOKEN:ATTRIBUTE_1==&#039;worker&#039;,&#039;bosses&#039;,&#039;workers&#039;)}?&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Information from previous answers= &amp;lt;!--T:24--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:25--&amp;gt;&lt;br /&gt;
There is currently also the capacity to insert the answer of previous questions into the text of an answer:&lt;br /&gt;
*You can refer to answers on the same page, and even dynamically update tailored messages as responses change on the page.&lt;br /&gt;
*You can use question code naming - for more details, see the [[Expression Manager|Expression Manager]] documentation&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:27--&amp;gt;&lt;br /&gt;
A wizard has been integrated in the Wysiwyg HTML editor (FCKeditor), so that you can easilly insert previous question/answer codes: this plugin is called the LimeReplacementFields. In order to use this feature, in the FCKeditor, click on the &amp;quot;lime between brackets&amp;quot; icon, and select a question from the select box. Only answers from previous pages are displayed.&lt;br /&gt;
&lt;br /&gt;
[[File:Editor_replacementfields_button.png]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:28--&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;simplebox&amp;quot;&amp;gt;LimeReplacementFields notice: when you want to delete a reference to a {name} tag, please select all chars from the openning bracket to the closing bracket and press delete: DO NOT erase it char by char with the Delete or Backspace key otherwise the field will appear again.&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Styling Questions= &amp;lt;!--T:29--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:30--&amp;gt;&lt;br /&gt;
It is possible to generally edit the question layout/design by using CSS using [[The template editor|the template editor]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/translate&amp;gt;&lt;/div&gt;</summary>
		<author><name>LimeAJ</name></author>
	</entry>
</feed>