<?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=Mdekker</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=Mdekker"/>
	<link rel="alternate" type="text/html" href="https://www.limesurvey.org/manual/Special:Contributions/Mdekker"/>
	<updated>2026-08-11T22:57:22Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.43.9</generator>
	<entry>
		<id>https://www.limesurvey.org/manual/index.php?title=BeforeSurveyPage&amp;diff=61268</id>
		<title>BeforeSurveyPage</title>
		<link rel="alternate" type="text/html" href="https://www.limesurvey.org/manual/index.php?title=BeforeSurveyPage&amp;diff=61268"/>
		<updated>2014-04-03T11:48:00Z</updated>

		<summary type="html">&lt;p&gt;Mdekker: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{FeatureStarting|2.05 build 140109}} &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;When&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This event is fired just before the survey (during runtime) is displayed on screen.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Input&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The event receives the followiong information:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;surveyId&#039;&#039; the id of the current survey&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Possible output&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The following information can be set in the event:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;template&#039;&#039; The name of the template to use&lt;/div&gt;</summary>
		<author><name>Mdekker</name></author>
	</entry>
	<entry>
		<id>https://www.limesurvey.org/manual/index.php?title=Plugin_events&amp;diff=61267</id>
		<title>Plugin events</title>
		<link rel="alternate" type="text/html" href="https://www.limesurvey.org/manual/index.php?title=Plugin_events&amp;diff=61267"/>
		<updated>2014-04-03T11:47:47Z</updated>

		<summary type="html">&lt;p&gt;Mdekker: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;At version 2.05+ build 140320 the following events are available for plugins to subscribe to:&lt;br /&gt;
*[[Authentication plugins|afterLoginFormSubmit]]&lt;br /&gt;
*[[Authentication plugins|afterLogout]]&lt;br /&gt;
*afterPluginLoad&lt;br /&gt;
*afterSurveyComplete&lt;br /&gt;
*beforeActivate&lt;br /&gt;
*beforeDeactivate&lt;br /&gt;
*[[Authentication plugins|beforeLogin]]&lt;br /&gt;
*[[Authentication plugins|beforeLogout]]&lt;br /&gt;
*beforePermissionSetSave&lt;br /&gt;
*[[beforeSurveyPage]]{{NewIn|v=2.05|b=140109}}&lt;br /&gt;
*beforeTokenEmail&lt;br /&gt;
*cron &lt;br /&gt;
*beforeSurveySettings&lt;br /&gt;
*listExportOptions&lt;br /&gt;
*listExportPlugins&lt;br /&gt;
*listQuestionPlugins&lt;br /&gt;
*newDirectRequest&lt;br /&gt;
*newExport&lt;br /&gt;
*[[Authentication plugins|newLoginForm]]&lt;br /&gt;
*newSurveySettings&lt;br /&gt;
*[[Authentication plugins|newUserSession]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Development]]&lt;br /&gt;
[[Category:Plugins]]&lt;/div&gt;</summary>
		<author><name>Mdekker</name></author>
	</entry>
	<entry>
		<id>https://www.limesurvey.org/manual/index.php?title=Authentication_plugins&amp;diff=61038</id>
		<title>Authentication plugins</title>
		<link rel="alternate" type="text/html" href="https://www.limesurvey.org/manual/index.php?title=Authentication_plugins&amp;diff=61038"/>
		<updated>2014-03-12T12:58:42Z</updated>

		<summary type="html">&lt;p&gt;Mdekker: &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 to 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;
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;
=== Webserver authentication ===&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>Mdekker</name></author>
	</entry>
	<entry>
		<id>https://www.limesurvey.org/manual/index.php?title=Plugins_-_advanced&amp;diff=61037</id>
		<title>Plugins - advanced</title>
		<link rel="alternate" type="text/html" href="https://www.limesurvey.org/manual/index.php?title=Plugins_-_advanced&amp;diff=61037"/>
		<updated>2014-03-12T12:58:23Z</updated>

		<summary type="html">&lt;p&gt;Mdekker: /* Available plugins */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
Starting from LimeSurvey 2.05, LimeSurvey will officially support plugins. Some plugins will be supported by the LimeSurvey team and will go into core. Some will be supported by others outside the LimeSurvey team. To help find them, check out the [[Available third party plugins]] and add your own plugin to it!&lt;br /&gt;
&lt;br /&gt;
Plugins allow users to customize the functionality of their installation while still being able to benefit from regular software updates.&lt;br /&gt;
&lt;br /&gt;
This documentation is meant for developers that are extending LimeSurvey for their own use or for their clients; end users will not be helped by this documentation.&lt;br /&gt;
&lt;br /&gt;
Plugins must implement the [https://github.com/LimeSurvey/LimeSurvey/blob/2.05/application/libraries/PluginManager/iPlugin.php iPlugin] interface. We recommend extending your plugin class from the [https://github.com/LimeSurvey/LimeSurvey/blob/2.05/application/libraries/PluginManager/PluginBase.php PluginBase] class.&lt;br /&gt;
&lt;br /&gt;
By extending you benefit from common functionality required by plugins that we already have implemented for you. One of these function is the implementation of the getPluginSettings function. This function must return an array describing the configuration options for the user.&lt;br /&gt;
&lt;br /&gt;
The example plugin exposes just 1 configurable setting, the message it&#039;ll show.&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;
protected $settings = array(&lt;br /&gt;
    &#039;logo&#039; =&amp;gt; array(&lt;br /&gt;
          &#039;type&#039; =&amp;gt; &#039;logo&#039;,&lt;br /&gt;
          &#039;path&#039; =&amp;gt; &#039;assets/logo.png&#039;&lt;br /&gt;
     ),&lt;br /&gt;
&lt;br /&gt;
     &#039;message&#039; =&amp;gt; array(&lt;br /&gt;
          &#039;type&#039; =&amp;gt; &#039;string&#039;,&lt;br /&gt;
          &#039;label&#039; =&amp;gt; &#039;Message&#039;&lt;br /&gt;
     )&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The array contains a name for each setting as a key. The values are arrays containing the required meta data.&lt;br /&gt;
&lt;br /&gt;
Supported types are:&lt;br /&gt;
&lt;br /&gt;
* logo&lt;br /&gt;
* string&lt;br /&gt;
* html&lt;br /&gt;
* choice&lt;br /&gt;
* relevance&lt;br /&gt;
&lt;br /&gt;
Besides type a number of other keys are available:&lt;br /&gt;
&lt;br /&gt;
* label, defines a label (use English, the label specified here will be passed through the translation functions)&lt;br /&gt;
* default, defines a value to show if no value is specified.&lt;br /&gt;
* current, defines the current value.&lt;br /&gt;
* readOnly, specifies the setting is read only.&lt;br /&gt;
&lt;br /&gt;
Plugins subscribe to events and can interact with LimeSurvey when the event is fired. For a list of currently available events check [[Plugin events]].&lt;br /&gt;
&lt;br /&gt;
== Special plugins ==&lt;br /&gt;
[[Authentication plugin development]]&lt;br /&gt;
&lt;br /&gt;
== Available plugins ==&lt;br /&gt;
* [[Authentication plugins]]&lt;br /&gt;
* [[Available third party plugins]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Development]]&lt;br /&gt;
[[Category:Plugins]]&lt;/div&gt;</summary>
		<author><name>Mdekker</name></author>
	</entry>
	<entry>
		<id>https://www.limesurvey.org/manual/index.php?title=Plugins_-_advanced&amp;diff=61036</id>
		<title>Plugins - advanced</title>
		<link rel="alternate" type="text/html" href="https://www.limesurvey.org/manual/index.php?title=Plugins_-_advanced&amp;diff=61036"/>
		<updated>2014-03-12T12:57:53Z</updated>

		<summary type="html">&lt;p&gt;Mdekker: /* Special plugins */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
Starting from LimeSurvey 2.05, LimeSurvey will officially support plugins. Some plugins will be supported by the LimeSurvey team and will go into core. Some will be supported by others outside the LimeSurvey team. To help find them, check out the [[Available third party plugins]] and add your own plugin to it!&lt;br /&gt;
&lt;br /&gt;
Plugins allow users to customize the functionality of their installation while still being able to benefit from regular software updates.&lt;br /&gt;
&lt;br /&gt;
This documentation is meant for developers that are extending LimeSurvey for their own use or for their clients; end users will not be helped by this documentation.&lt;br /&gt;
&lt;br /&gt;
Plugins must implement the [https://github.com/LimeSurvey/LimeSurvey/blob/2.05/application/libraries/PluginManager/iPlugin.php iPlugin] interface. We recommend extending your plugin class from the [https://github.com/LimeSurvey/LimeSurvey/blob/2.05/application/libraries/PluginManager/PluginBase.php PluginBase] class.&lt;br /&gt;
&lt;br /&gt;
By extending you benefit from common functionality required by plugins that we already have implemented for you. One of these function is the implementation of the getPluginSettings function. This function must return an array describing the configuration options for the user.&lt;br /&gt;
&lt;br /&gt;
The example plugin exposes just 1 configurable setting, the message it&#039;ll show.&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;
protected $settings = array(&lt;br /&gt;
    &#039;logo&#039; =&amp;gt; array(&lt;br /&gt;
          &#039;type&#039; =&amp;gt; &#039;logo&#039;,&lt;br /&gt;
          &#039;path&#039; =&amp;gt; &#039;assets/logo.png&#039;&lt;br /&gt;
     ),&lt;br /&gt;
&lt;br /&gt;
     &#039;message&#039; =&amp;gt; array(&lt;br /&gt;
          &#039;type&#039; =&amp;gt; &#039;string&#039;,&lt;br /&gt;
          &#039;label&#039; =&amp;gt; &#039;Message&#039;&lt;br /&gt;
     )&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The array contains a name for each setting as a key. The values are arrays containing the required meta data.&lt;br /&gt;
&lt;br /&gt;
Supported types are:&lt;br /&gt;
&lt;br /&gt;
* logo&lt;br /&gt;
* string&lt;br /&gt;
* html&lt;br /&gt;
* choice&lt;br /&gt;
* relevance&lt;br /&gt;
&lt;br /&gt;
Besides type a number of other keys are available:&lt;br /&gt;
&lt;br /&gt;
* label, defines a label (use English, the label specified here will be passed through the translation functions)&lt;br /&gt;
* default, defines a value to show if no value is specified.&lt;br /&gt;
* current, defines the current value.&lt;br /&gt;
* readOnly, specifies the setting is read only.&lt;br /&gt;
&lt;br /&gt;
Plugins subscribe to events and can interact with LimeSurvey when the event is fired. For a list of currently available events check [[Plugin events]].&lt;br /&gt;
&lt;br /&gt;
== Special plugins ==&lt;br /&gt;
[[Authentication plugin development]]&lt;br /&gt;
&lt;br /&gt;
== Available plugins ==&lt;br /&gt;
* [[Core plugins]]&lt;br /&gt;
* [[Available third party plugins]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Development]]&lt;br /&gt;
[[Category:Plugins]]&lt;/div&gt;</summary>
		<author><name>Mdekker</name></author>
	</entry>
	<entry>
		<id>https://www.limesurvey.org/manual/index.php?title=Authentication_plugin_development&amp;diff=61035</id>
		<title>Authentication plugin development</title>
		<link rel="alternate" type="text/html" href="https://www.limesurvey.org/manual/index.php?title=Authentication_plugin_development&amp;diff=61035"/>
		<updated>2014-03-12T12:53:54Z</updated>

		<summary type="html">&lt;p&gt;Mdekker: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
An authentication plugin has some additional requirements over a regular plugin. Here we list the requirements.&lt;br /&gt;
&lt;br /&gt;
To make creating your own authentication plugin easier, you should extend the abstract [https://github.com/LimeSurvey/LimeSurvey/blob/master/application/libraries/PluginManager/AuthPluginBase.php AuthPluginBase] class.&lt;br /&gt;
&lt;br /&gt;
To get an idea of the possibilities, check out the three core authentication plugins (check their pages for more information about configuration options):&lt;br /&gt;
* [https://github.com/LimeSurvey/LimeSurvey/blob/master/application/core/plugins/Authdb/Authdb.php Authdb] Database authentication - this is the default method for all new LimeSurvey installations.[[Authentication_plugins#Internal_database|info]]&lt;br /&gt;
* [https://github.com/LimeSurvey/LimeSurvey/blob/master/application/core/plugins/Authwebserver/Authwebserver.php Authwebserver] Webserver authentication - This one skips the login form, and provides methods for user creation. [[Authentication_plugins#Webserver_authentication|info]]&lt;br /&gt;
* [https://github.com/LimeSurvey/LimeSurvey/blob/master/application/core/plugins/AuthLDAP/AuthLDAP.php AuthLDAP] LDAP authentication - Adds a custom error message and relies on a user being present in the LimeSurvey database. [[Authentication_plugins#LDAP|info]]&lt;br /&gt;
&lt;br /&gt;
There are 6 events you can subscribe to:&lt;br /&gt;
&lt;br /&gt;
== beforeLogin ==&lt;br /&gt;
This is called first, and can possibly disable the loginform, for example when webserver authentication is used and we trust on that. To do this, use &#039;&#039;$this-&amp;gt;setAuthPlugin()&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== newLoginForm ==&lt;br /&gt;
Here you can add your own elements to the form. You should add your username/password elements, but could also add a domain selector or anything else you need. This will only be shown when the selected authentication method was chosen on the selector that is added when more then one plugin is present. When your authentication plugin does not need a form, and can not be selected as an option (like webserver authentication) you should not add a form element here.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$this-&amp;gt;getEvent()                  // Get the current event&lt;br /&gt;
     -&amp;gt;getContent($this)           // Get the content for this plugin&lt;br /&gt;
     -&amp;gt;addContent(CHtml::tag(      // And add some content to it&lt;br /&gt;
         &#039;li&#039;, &lt;br /&gt;
         array(), &lt;br /&gt;
         &amp;quot;&amp;lt;label for=&#039;user&#039;&amp;gt;&amp;quot;  . gT(&amp;quot;Username&amp;quot;) . &amp;quot;&amp;lt;/label&amp;gt;&amp;lt;input name=&#039;user&#039; id=&#039;user&#039; type=&#039;text&#039; size=&#039;40&#039; maxlength=&#039;40&#039; value=&#039;&#039; /&amp;gt;&amp;quot;))&lt;br /&gt;
     -&amp;gt;addContent(CHtml::tag(&lt;br /&gt;
         &#039;li&#039;, &lt;br /&gt;
         array(), &lt;br /&gt;
         &amp;quot;&amp;lt;label for=&#039;password&#039;&amp;gt;&amp;quot;  . gT(&amp;quot;Password&amp;quot;) . &amp;quot;&amp;lt;/label&amp;gt;&amp;lt;input name=&#039;password&#039; id=&#039;password&#039; type=&#039;password&#039; size=&#039;40&#039; maxlength=&#039;40&#039; value=&#039;&#039; /&amp;gt;&amp;quot;));&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== afterLoginFormSubmit ==&lt;br /&gt;
When the form for this plugin was submitted, this event is called. Here you can handle setting the values to the plugin. This event is also called when there was no form submitted and form display was canceled in the beforeLogin event.&lt;br /&gt;
&lt;br /&gt;
== newUserSession ==&lt;br /&gt;
This is where the real authentication takes place. You should use $this-&amp;gt;setAuthSuccess($oUser) for a successful attempt and provide a User object. If you fail to do so it will result in an authentication failure. If you need to provide a message about why the authentication failed, you can do so by using $this-&amp;gt;setAuthFailure($code, $message) where code is any code other than 0. The code is not used at this moment. The message should be a message in English, localised using the available tools in the plugin api. See the general plugin documenation for more information about that topic.&lt;br /&gt;
&lt;br /&gt;
== beforeLogout ==&lt;br /&gt;
This is fired before the user is destroyed and the session regenerated. This is the time for cleanup / logout in external systems if needed.&lt;br /&gt;
&lt;br /&gt;
== afterLogout ==&lt;br /&gt;
When the user is destroyed, you might want to redirect to a different page then currently defined. This is the right place to do so.&lt;br /&gt;
&lt;br /&gt;
[[Category:Plugins]]&lt;/div&gt;</summary>
		<author><name>Mdekker</name></author>
	</entry>
	<entry>
		<id>https://www.limesurvey.org/manual/index.php?title=Authentication_plugins&amp;diff=61034</id>
		<title>Authentication plugins</title>
		<link rel="alternate" type="text/html" href="https://www.limesurvey.org/manual/index.php?title=Authentication_plugins&amp;diff=61034"/>
		<updated>2014-03-12T12:53:00Z</updated>

		<summary type="html">&lt;p&gt;Mdekker: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&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 to 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;
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;
=== Webserver authentication ===&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>Mdekker</name></author>
	</entry>
	<entry>
		<id>https://www.limesurvey.org/manual/index.php?title=Authentication_plugins&amp;diff=61033</id>
		<title>Authentication plugins</title>
		<link rel="alternate" type="text/html" href="https://www.limesurvey.org/manual/index.php?title=Authentication_plugins&amp;diff=61033"/>
		<updated>2014-03-12T12:52:04Z</updated>

		<summary type="html">&lt;p&gt;Mdekker: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&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 to 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;
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;
=== Webserver authentication ===&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;/div&gt;</summary>
		<author><name>Mdekker</name></author>
	</entry>
	<entry>
		<id>https://www.limesurvey.org/manual/index.php?title=Authentication_plugins&amp;diff=61030</id>
		<title>Authentication plugins</title>
		<link rel="alternate" type="text/html" href="https://www.limesurvey.org/manual/index.php?title=Authentication_plugins&amp;diff=61030"/>
		<updated>2014-03-12T12:47:44Z</updated>

		<summary type="html">&lt;p&gt;Mdekker: Reverted edits by C schmitz (talk) to last revision by Mdekker&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;An authentication plugin has some additional requirements over a regular plugin. Here we list the requirements.&lt;br /&gt;
&lt;br /&gt;
To make creating your own authentication plugin easier, you should extend the abstract [https://github.com/LimeSurvey/LimeSurvey/blob/master/application/libraries/PluginManager/AuthPluginBase.php AuthPluginBase] class.&lt;br /&gt;
&lt;br /&gt;
To get an idea of the possibilities, check out the three core authentication plugins (check their pages for more information about configuration options):&lt;br /&gt;
* [https://github.com/LimeSurvey/LimeSurvey/blob/master/application/core/plugins/Authdb/Authdb.php Authdb] Database authentication - this is the default method for all new LimeSurvey installations.[[Core_plugins#Internal_database|info]]&lt;br /&gt;
* [https://github.com/LimeSurvey/LimeSurvey/blob/master/application/core/plugins/Authwebserver/Authwebserver.php Authwebserver] Webserver authentication - This one skips the login form, and provides methods for user creation. [[Core_plugins#Webserver_authentication|info]]&lt;br /&gt;
* [https://github.com/LimeSurvey/LimeSurvey/blob/master/application/core/plugins/AuthLDAP/AuthLDAP.php AuthLDAP] LDAP authentication - Adds a custom error message and relies on a user being present in the LimeSurvey database. [[Core_plugins#LDAP|info]]&lt;br /&gt;
&lt;br /&gt;
There are 6 events you can subscribe to:&lt;br /&gt;
&lt;br /&gt;
== beforeLogin ==&lt;br /&gt;
This is called first, and can possibly disable the loginform, for example when webserver authentication is used and we trust on that. To do this, use &#039;&#039;$this-&amp;gt;setAuthPlugin()&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== newLoginForm ==&lt;br /&gt;
Here you can add your own elements to the form. You should add your username/password elements, but could also add a domain selector or anything else you need. This will only be shown when the selected authentication method was chosen on the selector that is added when more then one plugin is present. When your authentication plugin does not need a form, and can not be selected as an option (like webserver authentication) you should not add a form element here.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$this-&amp;gt;getEvent()                  // Get the current event&lt;br /&gt;
     -&amp;gt;getContent($this)           // Get the content for this plugin&lt;br /&gt;
     -&amp;gt;addContent(CHtml::tag(      // And add some content to it&lt;br /&gt;
         &#039;li&#039;, &lt;br /&gt;
         array(), &lt;br /&gt;
         &amp;quot;&amp;lt;label for=&#039;user&#039;&amp;gt;&amp;quot;  . gT(&amp;quot;Username&amp;quot;) . &amp;quot;&amp;lt;/label&amp;gt;&amp;lt;input name=&#039;user&#039; id=&#039;user&#039; type=&#039;text&#039; size=&#039;40&#039; maxlength=&#039;40&#039; value=&#039;&#039; /&amp;gt;&amp;quot;))&lt;br /&gt;
     -&amp;gt;addContent(CHtml::tag(&lt;br /&gt;
         &#039;li&#039;, &lt;br /&gt;
         array(), &lt;br /&gt;
         &amp;quot;&amp;lt;label for=&#039;password&#039;&amp;gt;&amp;quot;  . gT(&amp;quot;Password&amp;quot;) . &amp;quot;&amp;lt;/label&amp;gt;&amp;lt;input name=&#039;password&#039; id=&#039;password&#039; type=&#039;password&#039; size=&#039;40&#039; maxlength=&#039;40&#039; value=&#039;&#039; /&amp;gt;&amp;quot;));&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== afterLoginFormSubmit ==&lt;br /&gt;
When the form for this plugin was submitted, this event is called. Here you can handle setting the values to the plugin. This event is also called when there was no form submitted and form display was canceled in the beforeLogin event.&lt;br /&gt;
&lt;br /&gt;
== newUserSession ==&lt;br /&gt;
This is where the real authentication takes place. You should use $this-&amp;gt;setAuthSuccess($oUser) for a successful attempt and provide a User object. If you fail to do so it will result in an authentication failure. If you need to provide a message about why the authentication failed, you can do so by using $this-&amp;gt;setAuthFailure($code, $message) where code is any code other than 0. The code is not used at this moment. The message should be a message in English, localised using the available tools in the plugin api. See the general plugin documenation for more information about that topic.&lt;br /&gt;
&lt;br /&gt;
== beforeLogout ==&lt;br /&gt;
This is fired before the user is destroyed and the session regenerated. This is the time for cleanup / logout in external systems if needed.&lt;br /&gt;
&lt;br /&gt;
== afterLogout ==&lt;br /&gt;
When the user is destroyed, you might want to redirect to a different page then currently defined. This is the right place to do so.&lt;br /&gt;
&lt;br /&gt;
[[Category:Plugins]]&lt;/div&gt;</summary>
		<author><name>Mdekker</name></author>
	</entry>
	<entry>
		<id>https://www.limesurvey.org/manual/index.php?title=BeforeSurveyPage&amp;diff=60426</id>
		<title>BeforeSurveyPage</title>
		<link rel="alternate" type="text/html" href="https://www.limesurvey.org/manual/index.php?title=BeforeSurveyPage&amp;diff=60426"/>
		<updated>2014-02-03T08:59:19Z</updated>

		<summary type="html">&lt;p&gt;Mdekker: Created page with &amp;quot;&amp;#039;&amp;#039;&amp;#039;When&amp;#039;&amp;#039;&amp;#039;  This event is fired just before the survey (during runtime) is displayed on screen.  &amp;#039;&amp;#039;&amp;#039;Input&amp;#039;&amp;#039;&amp;#039;  The event reveives the followiong information:  &amp;#039;&amp;#039;surveyId&amp;#039;&amp;#039; the ...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;When&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This event is fired just before the survey (during runtime) is displayed on screen.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Input&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The event reveives the followiong information:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;surveyId&#039;&#039; the id of the current survey&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Possible output&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The following information can be set in the event:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;template&#039;&#039; The name of the template to use&lt;/div&gt;</summary>
		<author><name>Mdekker</name></author>
	</entry>
	<entry>
		<id>https://www.limesurvey.org/manual/index.php?title=Plugin_events&amp;diff=60425</id>
		<title>Plugin events</title>
		<link rel="alternate" type="text/html" href="https://www.limesurvey.org/manual/index.php?title=Plugin_events&amp;diff=60425"/>
		<updated>2014-02-03T08:56:08Z</updated>

		<summary type="html">&lt;p&gt;Mdekker: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;At version 2.05RC1 the following events are available for plugins to subscribe to:&lt;br /&gt;
*[[Authentication plugins|afterLoginFormSubmit]]&lt;br /&gt;
*[[Authentication plugins|afterLogout]]&lt;br /&gt;
*afterPluginLoad&lt;br /&gt;
*afterSurveyComplete&lt;br /&gt;
*beforeActivate&lt;br /&gt;
*beforeDeactivate&lt;br /&gt;
*[[Authentication plugins|beforeLogin]]&lt;br /&gt;
*[[Authentication plugins|beforeLogout]]&lt;br /&gt;
*beforePermissionSetSave&lt;br /&gt;
*[[beforeSurveyPage]]&lt;br /&gt;
*beforeSurveySettings&lt;br /&gt;
*listExportOptions&lt;br /&gt;
*listExportPlugins&lt;br /&gt;
*listQuestionPlugins&lt;br /&gt;
*newDirectRequest&lt;br /&gt;
*newExport&lt;br /&gt;
*[[Authentication plugins|newLoginForm]]&lt;br /&gt;
*newSurveySettings&lt;br /&gt;
*[[Authentication plugins|newUserSession]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Development]]&lt;br /&gt;
[[Category:Plugins]]&lt;/div&gt;</summary>
		<author><name>Mdekker</name></author>
	</entry>
	<entry>
		<id>https://www.limesurvey.org/manual/index.php?title=Authentication_plugins&amp;diff=59657</id>
		<title>Authentication plugins</title>
		<link rel="alternate" type="text/html" href="https://www.limesurvey.org/manual/index.php?title=Authentication_plugins&amp;diff=59657"/>
		<updated>2013-12-10T09:51:02Z</updated>

		<summary type="html">&lt;p&gt;Mdekker: changed 2.05 to master for the links to github&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;An authentication plugin has some additional requirements over a regular plugin. Here we list the requirements.&lt;br /&gt;
&lt;br /&gt;
To make creating your own authentication plugin easier, you should extend the abstract [https://github.com/LimeSurvey/LimeSurvey/blob/master/application/libraries/PluginManager/AuthPluginBase.php AuthPluginBase] class.&lt;br /&gt;
&lt;br /&gt;
To get an idea of the possibilities, check out the three core authentication plugins (check their pages for more information about configuration options):&lt;br /&gt;
* [https://github.com/LimeSurvey/LimeSurvey/blob/master/application/core/plugins/Authdb/Authdb.php Authdb] Database authentication - this is the default method for all new LimeSurvey installations.[[Core_plugins#Internal_database|info]]&lt;br /&gt;
* [https://github.com/LimeSurvey/LimeSurvey/blob/master/application/core/plugins/Authwebserver/Authwebserver.php Authwebserver] Webserver authentication - This one skips the login form, and provides methods for user creation. [[Core_plugins#Webserver_authentication|info]]&lt;br /&gt;
* [https://github.com/LimeSurvey/LimeSurvey/blob/master/application/core/plugins/AuthLDAP/AuthLDAP.php AuthLDAP] LDAP authentication - Adds a custom error message and relies on a user being present in the LimeSurvey database. [[Core_plugins#LDAP|info]]&lt;br /&gt;
&lt;br /&gt;
There are 6 events you can subscribe to:&lt;br /&gt;
&lt;br /&gt;
== beforeLogin ==&lt;br /&gt;
This is called first, and can possibly disable the loginform, for example when webserver authentication is used and we trust on that. To do this, use &#039;&#039;$this-&amp;gt;setAuthPlugin()&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== newLoginForm ==&lt;br /&gt;
Here you can add your own elements to the form. You should add your username/password elements, but could also add a domain selector or anything else you need. This will only be shown when the selected authentication method was chosen on the selector that is added when more then one plugin is present. When your authentication plugin does not need a form, and can not be selected as an option (like webserver authentication) you should not add a form element here.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$this-&amp;gt;getEvent()                  // Get the current event&lt;br /&gt;
     -&amp;gt;getContent($this)           // Get the content for this plugin&lt;br /&gt;
     -&amp;gt;addContent(CHtml::tag(      // And add some content to it&lt;br /&gt;
         &#039;li&#039;, &lt;br /&gt;
         array(), &lt;br /&gt;
         &amp;quot;&amp;lt;label for=&#039;user&#039;&amp;gt;&amp;quot;  . gT(&amp;quot;Username&amp;quot;) . &amp;quot;&amp;lt;/label&amp;gt;&amp;lt;input name=&#039;user&#039; id=&#039;user&#039; type=&#039;text&#039; size=&#039;40&#039; maxlength=&#039;40&#039; value=&#039;&#039; /&amp;gt;&amp;quot;))&lt;br /&gt;
     -&amp;gt;addContent(CHtml::tag(&lt;br /&gt;
         &#039;li&#039;, &lt;br /&gt;
         array(), &lt;br /&gt;
         &amp;quot;&amp;lt;label for=&#039;password&#039;&amp;gt;&amp;quot;  . gT(&amp;quot;Password&amp;quot;) . &amp;quot;&amp;lt;/label&amp;gt;&amp;lt;input name=&#039;password&#039; id=&#039;password&#039; type=&#039;password&#039; size=&#039;40&#039; maxlength=&#039;40&#039; value=&#039;&#039; /&amp;gt;&amp;quot;));&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== afterLoginFormSubmit ==&lt;br /&gt;
When the form for this plugin was submitted, this event is called. Here you can handle setting the values to the plugin. This event is also called when there was no form submitted and form display was canceled in the beforeLogin event.&lt;br /&gt;
&lt;br /&gt;
== newUserSession ==&lt;br /&gt;
This is where the real authentication takes place. You should use $this-&amp;gt;setAuthSuccess($oUser) for a successful attempt and provide a User object. If you fail to do so it will result in an authentication failure. If you need to provide a message about why the authentication failed, you can do so by using $this-&amp;gt;setAuthFailure($code, $message) where code is any code other than 0. The code is not used at this moment. The message should be a message in English, localised using the available tools in the plugin api. See the general plugin documenation for more information about that topic.&lt;br /&gt;
&lt;br /&gt;
== beforeLogout ==&lt;br /&gt;
This is fired before the user is destroyed and the session regenerated. This is the time for cleanup / logout in external systems if needed.&lt;br /&gt;
&lt;br /&gt;
== afterLogout ==&lt;br /&gt;
When the user is destroyed, you might want to redirect to a different page then currently defined. This is the right place to do so.&lt;br /&gt;
&lt;br /&gt;
[[Category:Plugins]]&lt;/div&gt;</summary>
		<author><name>Mdekker</name></author>
	</entry>
	<entry>
		<id>https://www.limesurvey.org/manual/index.php?title=Authentication_plugins&amp;diff=57730</id>
		<title>Authentication plugins</title>
		<link rel="alternate" type="text/html" href="https://www.limesurvey.org/manual/index.php?title=Authentication_plugins&amp;diff=57730"/>
		<updated>2013-10-16T10:44:48Z</updated>

		<summary type="html">&lt;p&gt;Mdekker: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;An authentication plugin has some additional requirements over a regular plugin. Here we list the requirements.&lt;br /&gt;
&lt;br /&gt;
To make creating your own authentication plugin easier, you should extend the abstract [https://github.com/LimeSurvey/LimeSurvey/blob/2.05/application/libraries/PluginManager/AuthPluginBase.php AuthPluginBase] class.&lt;br /&gt;
&lt;br /&gt;
To get an idea of the possibilities, check out the three core authentication plugins (check their pages for more information about configuration options):&lt;br /&gt;
* [https://github.com/LimeSurvey/LimeSurvey/blob/2.05/application/core/plugins/Authdb/Authdb.php Authdb] Database authentication - this is the default method for all new LimeSurvey installations.[[Core_plugins#Internal_database|info]]&lt;br /&gt;
* [https://github.com/LimeSurvey/LimeSurvey/blob/2.05/application/core/plugins/Authwebserver/Authwebserver.php Authwebserver] Webserver authentication - This one skips the login form, and provides methods for user creation. [[Core_plugins#Webserver_authentication|info]]&lt;br /&gt;
* [https://github.com/LimeSurvey/LimeSurvey/blob/2.05/application/core/plugins/AuthLDAP/AuthLDAP.php AuthLDAP] LDAP authentication - Adds a custom error message and relies on a user being present in the LimeSurvey database. [[Core_plugins#LDAP|info]]&lt;br /&gt;
&lt;br /&gt;
There are 6 events you can subscribe to:&lt;br /&gt;
&lt;br /&gt;
== beforeLogin ==&lt;br /&gt;
This is called first, and can possibly disable the loginform, for example when webserver authentication is used and we trust on that. To do this, use &#039;&#039;$this-&amp;gt;setAuthPlugin()&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== newLoginForm ==&lt;br /&gt;
Here you can add your own elements to the form. You should add your username/password elements, but could also add a domain selector or anything else you need. This will only be shown when the selected authentication method was chosen on the selector that is added when more then one plugin is present. When your authentication plugin does not need a form, and can not be selected as an option (like webserver authentication) you should not add a form element here.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$this-&amp;gt;getEvent()                  // Get the current event&lt;br /&gt;
     -&amp;gt;getContent($this)           // Get the content for this plugin&lt;br /&gt;
     -&amp;gt;addContent(CHtml::tag(      // And add some content to it&lt;br /&gt;
         &#039;li&#039;, &lt;br /&gt;
         array(), &lt;br /&gt;
         &amp;quot;&amp;lt;label for=&#039;user&#039;&amp;gt;&amp;quot;  . gT(&amp;quot;Username&amp;quot;) . &amp;quot;&amp;lt;/label&amp;gt;&amp;lt;input name=&#039;user&#039; id=&#039;user&#039; type=&#039;text&#039; size=&#039;40&#039; maxlength=&#039;40&#039; value=&#039;&#039; /&amp;gt;&amp;quot;))&lt;br /&gt;
     -&amp;gt;addContent(CHtml::tag(&lt;br /&gt;
         &#039;li&#039;, &lt;br /&gt;
         array(), &lt;br /&gt;
         &amp;quot;&amp;lt;label for=&#039;password&#039;&amp;gt;&amp;quot;  . gT(&amp;quot;Password&amp;quot;) . &amp;quot;&amp;lt;/label&amp;gt;&amp;lt;input name=&#039;password&#039; id=&#039;password&#039; type=&#039;password&#039; size=&#039;40&#039; maxlength=&#039;40&#039; value=&#039;&#039; /&amp;gt;&amp;quot;));&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== afterLoginFormSubmit ==&lt;br /&gt;
When the form for this plugin was submitted, this event is called. Here you can handle setting the values to the plugin. This event is also called when there was no form submitted and form display was canceled in the beforeLogin event.&lt;br /&gt;
&lt;br /&gt;
== newUserSession ==&lt;br /&gt;
This is where the real authentication takes place. You should use $this-&amp;gt;setAuthSuccess($oUser) for a successful attempt and provide a User object. If you fail to do so it will result in an authentication failure. If you need to provide a message about why the authentication failed, you can do so by using $this-&amp;gt;setAuthFailure($code, $message) where code is any code other than 0. The code is not used at this moment. The message should be a message in English, localised using the available tools in the plugin api. See the general plugin documenation for more information about that topic.&lt;br /&gt;
&lt;br /&gt;
== beforeLogout ==&lt;br /&gt;
This is fired before the user is destroyed and the session regenerated. This is the time for cleanup / logout in external systems if needed.&lt;br /&gt;
&lt;br /&gt;
== afterLogout ==&lt;br /&gt;
When the user is destroyed, you might want to redirect to a different page then currently defined. This is the right place to do so.&lt;br /&gt;
&lt;br /&gt;
[[Category:Plugins]]&lt;/div&gt;</summary>
		<author><name>Mdekker</name></author>
	</entry>
	<entry>
		<id>https://www.limesurvey.org/manual/index.php?title=Plugins_-_advanced&amp;diff=57726</id>
		<title>Plugins - advanced</title>
		<link rel="alternate" type="text/html" href="https://www.limesurvey.org/manual/index.php?title=Plugins_-_advanced&amp;diff=57726"/>
		<updated>2013-10-16T10:14:40Z</updated>

		<summary type="html">&lt;p&gt;Mdekker: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
Starting from LimeSurvey 2.05, LimeSurvey will officially support plugins. Some plugins will be supported by the LimeSurvey team and will go into core. Some will be supported by others outside the LimeSurvey team. To help find them, check out the [[Available third party plugins]] and add your own plugin to it!&lt;br /&gt;
&lt;br /&gt;
Plugins allow users to customize the functionality of their installation while still being able to benefit from regular software updates.&lt;br /&gt;
&lt;br /&gt;
This documentation is meant for developers that are extending LimeSurvey for their own use or for their clients; end users will not be helped by this documentation.&lt;br /&gt;
&lt;br /&gt;
Plugins must implement the [https://github.com/LimeSurvey/LimeSurvey/blob/2.05/application/libraries/PluginManager/iPlugin.php iPlugin] interface. We recommend extending your plugin class from the [https://github.com/LimeSurvey/LimeSurvey/blob/2.05/application/libraries/PluginManager/PluginBase.php PluginBase] class.&lt;br /&gt;
&lt;br /&gt;
By extending you benefit from common functionality required by plugins that we already have implemented for you. One of these function is the implementation of the getPluginSettings function. This function must return an array describing the configuration options for the user.&lt;br /&gt;
&lt;br /&gt;
The example plugin exposes just 1 configurable setting, the message it&#039;ll show.&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;
protected $settings = array(&lt;br /&gt;
    &#039;logo&#039; =&amp;gt; array(&lt;br /&gt;
          &#039;type&#039; =&amp;gt; &#039;logo&#039;,&lt;br /&gt;
          &#039;path&#039; =&amp;gt; &#039;assets/logo.png&#039;&lt;br /&gt;
     ),&lt;br /&gt;
&lt;br /&gt;
     &#039;message&#039; =&amp;gt; array(&lt;br /&gt;
          &#039;type&#039; =&amp;gt; &#039;string&#039;,&lt;br /&gt;
          &#039;label&#039; =&amp;gt; &#039;Message&#039;&lt;br /&gt;
     )&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The array contains a name for each setting as a key. The values are arrays containing the required meta data.&lt;br /&gt;
&lt;br /&gt;
Supported types are:&lt;br /&gt;
&lt;br /&gt;
* logo&lt;br /&gt;
* string&lt;br /&gt;
* html&lt;br /&gt;
* choice&lt;br /&gt;
* relevance&lt;br /&gt;
&lt;br /&gt;
Besides type a number of other keys are available:&lt;br /&gt;
&lt;br /&gt;
* label, defines a label (use English, the label specified here will be passed through the translation functions)&lt;br /&gt;
* default, defines a value to show if no value is specified.&lt;br /&gt;
* current, defines the current value.&lt;br /&gt;
* readOnly, specifies the setting is read only.&lt;br /&gt;
&lt;br /&gt;
Plugins subscribe to events and can interact with LimeSurvey when the event is fired. For a list of currently available events check [[Plugin events]].&lt;br /&gt;
&lt;br /&gt;
== Special plugins ==&lt;br /&gt;
[[Authentication plugins]]&lt;br /&gt;
&lt;br /&gt;
== Available plugins ==&lt;br /&gt;
* [[Core plugins]]&lt;br /&gt;
* [[Available third party plugins]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Development]]&lt;br /&gt;
[[Category:Plugins]]&lt;/div&gt;</summary>
		<author><name>Mdekker</name></author>
	</entry>
	<entry>
		<id>https://www.limesurvey.org/manual/index.php?title=Plugins_-_advanced&amp;diff=57725</id>
		<title>Plugins - advanced</title>
		<link rel="alternate" type="text/html" href="https://www.limesurvey.org/manual/index.php?title=Plugins_-_advanced&amp;diff=57725"/>
		<updated>2013-10-16T10:13:39Z</updated>

		<summary type="html">&lt;p&gt;Mdekker: /* Available plugins */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
Starting from LimeSurvey 2.05, LimeSurvey will officially support plugins. Some plugins will be supported by the LimeSurvey team and will go into core. Some will be supported by others outside the LimeSurvey team. To help find them, check out the [[Available third party plugins]] and add your own plugin to it!&lt;br /&gt;
&lt;br /&gt;
Plugins allow users to customize the functionality of their installation while still being able to benefit from regular software updates.&lt;br /&gt;
&lt;br /&gt;
This documentation is meant for developers that are extending LimeSurvey for their own use or for their clients; end users will not be helped by this documentation.&lt;br /&gt;
&lt;br /&gt;
Plugins must implement the [https://github.com/LimeSurvey/LimeSurvey/blob/2.05/application/libraries/PluginManager/iPlugin.php iPlugin] interface. We recommend extending your plugin class from the [https://github.com/LimeSurvey/LimeSurvey/blob/2.05/application/libraries/PluginManager/PluginBase.php PluginBase] class.&lt;br /&gt;
&lt;br /&gt;
By extending you benefit from common functionality required by plugins that we already have implemented for you. One of these function is the implementation of the getPluginSettings function. This function must return an array describing the configuration options for the user.&lt;br /&gt;
&lt;br /&gt;
The example plugin exposes just 1 configurable setting, the message it&#039;ll show.&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;
protected $settings = array(&lt;br /&gt;
    &#039;logo&#039; =&amp;gt; array(&lt;br /&gt;
          &#039;type&#039; =&amp;gt; &#039;logo&#039;,&lt;br /&gt;
          &#039;path&#039; =&amp;gt; &#039;assets/logo.png&#039;&lt;br /&gt;
     ),&lt;br /&gt;
&lt;br /&gt;
     &#039;message&#039; =&amp;gt; array(&lt;br /&gt;
          &#039;type&#039; =&amp;gt; &#039;string&#039;,&lt;br /&gt;
          &#039;label&#039; =&amp;gt; &#039;Message&#039;&lt;br /&gt;
     )&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The array contains a name for each setting as a key. The values are arrays containing the required meta data.&lt;br /&gt;
&lt;br /&gt;
Supported types are:&lt;br /&gt;
&lt;br /&gt;
* logo&lt;br /&gt;
* string&lt;br /&gt;
* html&lt;br /&gt;
* choice&lt;br /&gt;
* relevance&lt;br /&gt;
&lt;br /&gt;
Besides type a number of other keys are available:&lt;br /&gt;
&lt;br /&gt;
* label, defines a label (use English, the label specified here will be passed through the translation functions)&lt;br /&gt;
* default, defines a value to show if no value is specified.&lt;br /&gt;
* current, defines the current value.&lt;br /&gt;
* readOnly, specifies the setting is read only.&lt;br /&gt;
&lt;br /&gt;
Plugins subscribe to events and can interact with LimeSurvey when the event is fired. For a list of currently available events check [[Plugin events]].&lt;br /&gt;
&lt;br /&gt;
== Special plugins ==&lt;br /&gt;
[[Authentication plugins]]&lt;br /&gt;
&lt;br /&gt;
== Available plugins ==&lt;br /&gt;
 * [[Core plugins]]&lt;br /&gt;
 * [[Available third party plugins]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Development]]&lt;br /&gt;
[[Category:Plugins]]&lt;/div&gt;</summary>
		<author><name>Mdekker</name></author>
	</entry>
	<entry>
		<id>https://www.limesurvey.org/manual/index.php?title=Plugins_-_advanced&amp;diff=57724</id>
		<title>Plugins - advanced</title>
		<link rel="alternate" type="text/html" href="https://www.limesurvey.org/manual/index.php?title=Plugins_-_advanced&amp;diff=57724"/>
		<updated>2013-10-16T10:13:24Z</updated>

		<summary type="html">&lt;p&gt;Mdekker: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
Starting from LimeSurvey 2.05, LimeSurvey will officially support plugins. Some plugins will be supported by the LimeSurvey team and will go into core. Some will be supported by others outside the LimeSurvey team. To help find them, check out the [[Available third party plugins]] and add your own plugin to it!&lt;br /&gt;
&lt;br /&gt;
Plugins allow users to customize the functionality of their installation while still being able to benefit from regular software updates.&lt;br /&gt;
&lt;br /&gt;
This documentation is meant for developers that are extending LimeSurvey for their own use or for their clients; end users will not be helped by this documentation.&lt;br /&gt;
&lt;br /&gt;
Plugins must implement the [https://github.com/LimeSurvey/LimeSurvey/blob/2.05/application/libraries/PluginManager/iPlugin.php iPlugin] interface. We recommend extending your plugin class from the [https://github.com/LimeSurvey/LimeSurvey/blob/2.05/application/libraries/PluginManager/PluginBase.php PluginBase] class.&lt;br /&gt;
&lt;br /&gt;
By extending you benefit from common functionality required by plugins that we already have implemented for you. One of these function is the implementation of the getPluginSettings function. This function must return an array describing the configuration options for the user.&lt;br /&gt;
&lt;br /&gt;
The example plugin exposes just 1 configurable setting, the message it&#039;ll show.&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;
protected $settings = array(&lt;br /&gt;
    &#039;logo&#039; =&amp;gt; array(&lt;br /&gt;
          &#039;type&#039; =&amp;gt; &#039;logo&#039;,&lt;br /&gt;
          &#039;path&#039; =&amp;gt; &#039;assets/logo.png&#039;&lt;br /&gt;
     ),&lt;br /&gt;
&lt;br /&gt;
     &#039;message&#039; =&amp;gt; array(&lt;br /&gt;
          &#039;type&#039; =&amp;gt; &#039;string&#039;,&lt;br /&gt;
          &#039;label&#039; =&amp;gt; &#039;Message&#039;&lt;br /&gt;
     )&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The array contains a name for each setting as a key. The values are arrays containing the required meta data.&lt;br /&gt;
&lt;br /&gt;
Supported types are:&lt;br /&gt;
&lt;br /&gt;
* logo&lt;br /&gt;
* string&lt;br /&gt;
* html&lt;br /&gt;
* choice&lt;br /&gt;
* relevance&lt;br /&gt;
&lt;br /&gt;
Besides type a number of other keys are available:&lt;br /&gt;
&lt;br /&gt;
* label, defines a label (use English, the label specified here will be passed through the translation functions)&lt;br /&gt;
* default, defines a value to show if no value is specified.&lt;br /&gt;
* current, defines the current value.&lt;br /&gt;
* readOnly, specifies the setting is read only.&lt;br /&gt;
&lt;br /&gt;
Plugins subscribe to events and can interact with LimeSurvey when the event is fired. For a list of currently available events check [[Plugin events]].&lt;br /&gt;
&lt;br /&gt;
== Special plugins ==&lt;br /&gt;
[[Authentication plugins]]&lt;br /&gt;
&lt;br /&gt;
== Available plugins ==&lt;br /&gt;
[[Core plugins]]&lt;br /&gt;
[[Available third party plugins]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Development]]&lt;br /&gt;
[[Category:Plugins]]&lt;/div&gt;</summary>
		<author><name>Mdekker</name></author>
	</entry>
	<entry>
		<id>https://www.limesurvey.org/manual/index.php?title=Optional_settings&amp;diff=57723</id>
		<title>Optional settings</title>
		<link rel="alternate" type="text/html" href="https://www.limesurvey.org/manual/index.php?title=Optional_settings&amp;diff=57723"/>
		<updated>2013-10-16T10:10:25Z</updated>

		<summary type="html">&lt;p&gt;Mdekker: &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;
=Note= &amp;lt;!--T:2--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:3--&amp;gt;&lt;br /&gt;
These optional settings can only be found in the file /application/config/config-defaults.php of a standard installation - some of them are only used for first installation and overriden in [[Global settings]]. &lt;br /&gt;
{{Alert|If you want to change these settings please do not change it in config-defaults.php but copy the particular setting/line over to /application/config/config.php in &amp;lt;nowiki&amp;gt;&#039;config&#039;=&amp;gt;array()&amp;lt;/nowiki&amp;gt; and change it there.}}&lt;br /&gt;
All settings in config.php overwrite the default values from config-defaults.php and some of these settings get overridden in the Global settings dialog{{NewIn|1.87}} . This way it is much easier to upgrade your installation at a later time!&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;: Give your survey site a name. This name will appear in the survey list overview and in the administration header. This setting is overridden in the [[Global settings]] dialog {{NewIn|1.87}}.&lt;br /&gt;
*&#039;&#039;&#039;siteadminemail:&#039;&#039;&#039; This is the default email address of the site administrator and used for system messages and contact options. This setting is overridden by the [[Global settings]] dialog {{NewIn|1.87}}.&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 overridden by the [[Global settings]] dialog {{NewIn|1.87}}.&lt;br /&gt;
*&#039;&#039;&#039;siteadminname:&#039;&#039;&#039; The real name of the site administrator. This setting is overridden in the [[Global settings]] dialog) {{NewIn|1.87}}.&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;surveyPreview_require_Auth&#039;&#039;&#039;: true by default. If you set this to false any person can test your survey using the survey URL - without logging in to the administration and without having to activate the survey first. This setting is overridden in the [[Global settings]] dialog) {{NewIn|1.87}}.&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 user belongs to,at least one, same group. You can deactivate this behaviour.&lt;br /&gt;
*&#039;&#039;&#039;filterxsshtml:&#039;&#039;&#039; This setting enables filtering of suspicious html tags in survey, group, questions and answer texts in the administration interface. Only leave this to &#039;false&#039; 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;Super admin never have their HTML filtered&amp;lt;/span&amp;gt;. This setting is overridden in the [[Global settings]] dialog) {{NewIn|1.87}}.&lt;br /&gt;
*&#039;&#039;&#039;demoModeOnly:&#039;&#039;&#039; If this option is set to true, then LimeSurvey will go into demo mode. The demo mode changes the following things:&lt;br /&gt;
** Disables changing of the admin user&#039;s details and password&lt;br /&gt;
** Disables uploading files on the template editor&lt;br /&gt;
** Disables sending email invitations and reminders&lt;br /&gt;
** Disables doing a database dump&lt;br /&gt;
** Disables the ability to save the following global settings: Site name, Default language, Default Htmleditor 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. Default: $sessionlifetime    =  3600; .This setting is overridden in the [[Global settings]] dialog) {{NewIn|1.87}}.&lt;br /&gt;
*&#039;&#039;&#039;memorylimit:&#039;&#039;&#039; This sets how much memory LimeSurvey can access. &#039;32&#039; is the minimum (M=mb) recommended. If you receive time out errors or have problems generating statistics or exporting files raise this limit to &#039;128&#039; or &#039;256&#039;.&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;Please mind that such local settings by an application can always be overruled by global server settings.&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;$lwcdropdowns:&#039;&#039;&#039;{{ObsoleteIn|2.0}} This can be set to either &amp;quot;L&amp;quot; or &amp;quot;R&amp;quot;. Setting it to &amp;quot;R&amp;quot; will result in &#039;List with Comment&#039; questions being displayed as radio buttons, whereas &amp;quot;L&amp;quot; will result in &#039;List with Comment&#039; questions being displayed in a &#039;dropdown&#039; list box .&lt;br /&gt;
*&#039;&#039;&#039;$dropdownthreshold:&#039;&#039;&#039; When you have selected &amp;quot;R&amp;quot; for $dropdowns, this allows you to set a maximum number of options that will display as radio buttons, before converting back to a dropdown list. If you have a question that has a large number of options, displaying them all as radio buttons can look unweildy, and be counter-intuitive to users. Setting this to a maximum of, say 25 (which is the default) means that large lists are easier for the survey participant to use.&lt;br /&gt;
*&#039;&#039;&#039;$repeatheadings:&#039;&#039;&#039; With the array (flexible) type question, often you&#039;ll have a lot of answers, which - when displayed on screen - take up more than one page. The repeat-headers setting lets you decide how many answers 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 (which is the default).&lt;br /&gt;
*&#039;&#039;&#039;$minrepeatheadings:&#039;&#039;&#039; The minimum number of reaming answers that are required before repeating the headings in array (flexible) questions.&lt;br /&gt;
*&#039;&#039;&#039;$addTitleToLinks:&#039;&#039;&#039; If this option is set to true, then LimeSurvey will add &#039;title&#039; html element to all links used in menus. This will help screen reader to analyze the menus. Only set this to true if you&#039;re using a screen reader because it overlaps with tool tips.&lt;br /&gt;
*&#039;&#039;&#039;$defaulttemplate:&#039;&#039;&#039; This setting specifys the default theme used for the &#039;public list&#039; of surveys. This setting is overridden in the [[Global settings]] dialog) {{NewIn|1.87}}.&lt;br /&gt;
*&#039;&#039;&#039;$defaulthtmleditormode:&#039;&#039;&#039; Sets the default mode for integrated HTML editor. This setting is overridden in the [[Global settings]] dialog) {{NewIn|1.87}}. Valid settings are: inline (default), popup and none:&lt;br /&gt;
** &#039;&#039;inline&#039;&#039;: Inline replacement of fields by an HTML editor. Slow but convenient and user friendly&lt;br /&gt;
** &#039;&#039;popup&#039;&#039;: Adds an icon that runs a popup with and html editor. Faster, but html code is displayed on the form&lt;br /&gt;
** &#039;&#039;none&#039;&#039;: No html editor&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 surveys. You can change this setting for public surveys on a survey-by-survey basis from the admin scripts.  This setting is overridden in the [[Global settings]] dialog) {{NewIn|1.87}}.&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 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 is overridden in the [[Global settings]] dialog) {{NewIn|1.87}}.&lt;br /&gt;
* &#039;&#039;&#039;$modrewrite:&#039;&#039;&#039; {{ObsoleteIn|2.0}} If set to 1, it activates the fancy URL feature (Example: http://survey.example.com/123456/lang-fr/tk-sdlfkjozeiru instead of http://survey.example.com/index.php?sid=123456&amp;amp;lang;=fr&amp;amp;token;=sdlfkjozeiru). Before you activate this, you &amp;lt;u&amp;gt;must&amp;lt;/u&amp;gt; rename &amp;quot;&#039;&#039;htaccess.txt&#039;&#039;&amp;quot; file to &amp;quot;&#039;&#039;.htaccess&#039;&#039;&amp;quot;. You need to run an Apache web server with correctly installed mod_rewrite module.&lt;br /&gt;
&lt;br /&gt;
=Survey Behavior= &amp;lt;!--T:10--&amp;gt;&lt;br /&gt;
*&#039;&#039;&#039;$allowmandbackwards:&#039;&#039;&#039; A setting of 1 for this variable will allow survey participants to move to a previous question even if they haven&#039;t answered a mandatory question. If it is set on 0, then participants will have to answer that question even to move to a previous question.&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.  Say 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 $deletenonvalues==1, those irrelevant values will be cleared (NULLed) in the database.  If $deletenonvalues==0, 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 question of a radio button/select type that contains editable answers (ie: List, Array questions) is not mandatory and $shownoanswer is set to 1, an additional entry is shown for &amp;quot;N/A&amp;quot; - so that participants may choose to not answer the question. Some people prefer this not to be available. Set this to 0 to turn this off.  This setting is overridden in the [[Global settings]] dialog) {{NewIn|1.87}}.&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;{{NewIn|1.85RC3}} This setting is relevant for all-in-one surveys using conditions . When this is set to true the group name and description is hidden if all questions in the group are hidden. (Default: true (hide group name and description when all conditions in the group are hidden by conditions))&lt;br /&gt;
*&#039;&#039;&#039;$showpopups:&#039;&#039;&#039;  Show popup messages if mandatory or conditional questions have not been answered correctly. 1=Show popup message (default), 0=Show message on page instead, -1=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= &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. That means every little notice, warning or error with the script is shown. This setting should be only switched to 1 if you are trying to debug the application for any reason, if you are a developer switch it to 2. Don&#039;t switch it to 1 or 2 in production since it might cause path disclosure. (Default: 0)&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;
Note: All these settings in this section are overridden in the [[Global settings]] dialog{{NewIn|1.87}}.&lt;br /&gt;
*&#039;&#039;&#039;$emailmethod:&#039;&#039;&#039;  This determines how E-mail messages are being sent. The following options are available:&lt;br /&gt;
**&#039;&#039;&#039;mail:&#039;&#039;&#039; use internal PHP mailer&lt;br /&gt;
**&#039;&#039;&#039;sendmail:&#039;&#039;&#039; use sendmail mailer&lt;br /&gt;
**&#039;&#039;&#039;smtp:&#039;&#039;&#039;use 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;&#039;&#039; If you use &#039;smtp&#039; as $emailmethod 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;&#039;&#039;$emailsmtpuser:&#039;&#039;&#039; If your SMTP-server needs authentication then set this to your user name, otherwise it must be blank.&lt;br /&gt;
*&#039;&#039;&#039;$emailsmtppassword:&#039;&#039;&#039; If your SMTP-server needs authentication then set this to your password, otherwise it must be blank.&lt;br /&gt;
*&#039;&#039;&#039;$emailsmtpssl:&#039;&#039;&#039; Set this to &#039;ssl&#039; or &#039;tls&#039; to use SSL/TLS for SMTP connection&lt;br /&gt;
*&#039;&#039;&#039;$maxemails:&#039;&#039;&#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 on the token control toolbar, (not the button on the right of each token), sends the maxemails number of invitations, then displays a list of the addresses sent to and a warning that &amp;quot;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.&amp;quot; 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 off 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;usejpgraph:&#039;&#039;&#039; {{ObsoleteIn|1.8}} The [http://www.aditus.nu/jpgraph/ JPGraph-library] lets you display the results of your survey in the statistics part of LimeSurvey  in bar- and pie charts. If you have a correctly configured jpgraph class set up on your server, you can turn this feature on or off (1=on, 0=off). Please have a look, every version of PHP needs another version of JPGraph! This feature is currently in development, so expect a few weird outcomes.&lt;br /&gt;
*&#039;&#039;&#039;jpgraphdir:&#039;&#039;&#039; {{ObsoleteIn|1.8}} The physical disk location of the jpgraph class scripts. This setting is only required if $usejpgraph is equal to 1.&lt;br /&gt;
*&#039;&#039;&#039;jpgraphfont:&#039;&#039;&#039; {{ObsoleteIn|1.8}} The font to use with graphs. A failsafe setting would be &amp;quot;FF_FONT1&amp;quot;&lt;br /&gt;
*&#039;&#039;&#039;embedded:&#039;&#039;&#039;{{ObsoleteIn|2.0}} If you want to integrate LimeSurvey into another page then you can turn off sending HTML headers by using this setting and point instead to the header method of a custom function. This is a dirty hack but should work for a quick integration.&lt;br /&gt;
*&#039;&#039;&#039;filterout_incomplete_answers:&#039;&#039;&#039; Control the default behaviour of  filtering incomplete answers when browsing or analyzing responses. For a discussion on incomplete Responses see [[Browsing survey results]]. Since these records can corrupt the statistics, an option is given to switch this filter on or off in several GUI forms. This parameter config.php is just the default state for the incomplete answer filter. The following options are available:&lt;br /&gt;
**&#039;&#039;show&#039;&#039;: Show both complete and incomplete answers&lt;br /&gt;
**&#039;&#039;filter&#039;&#039;: Show only complete answers&lt;br /&gt;
**&#039;&#039;incomplete&#039;&#039;: Show only incomplete answers&lt;br /&gt;
*&#039;&#039;&#039;strip_query_from_referer_url&#039;&#039;&#039;: This setting determine if the referrer URL saves parameter or not. Default value is &amp;quot;false&amp;quot; (in this case referrer URL saves all parameter). Alternatively this value can be set to &amp;quot;true&amp;quot; and the parameter part of the referrer URL will be removed.&lt;br /&gt;
*&#039;&#039;&#039;showaggregateddata:&#039;&#039;&#039; {{NewIn|1.8}} When activated there are additional values like arithmetic mean and standard deviation at statistics. Furthermore data is aggregated to get a faster overview e.g. 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; {{NewIn|1.85}} This feature activates PDF export for printable survey and Print Answers. The PDF export is totally experimental. The output is mostly ugly. At this point no support can be given - if you want to help to fix it please get in touch with us.&lt;br /&gt;
**usepdfexport: Set 0 to disable; 1 to enable&lt;br /&gt;
**pdfdefaultfont: Default font for the pdf Export&lt;br /&gt;
**pdffontsize: Fontsize for normal text; Surveytitle is +4; grouptitle is +2&lt;br /&gt;
**notsupportlanguages = array(&#039;zh-Hant-TW&#039;,&#039;zh-Hant-HK&#039;,&#039;zh-Hans&#039;,&#039;ja&#039;,&#039;th&#039;);&lt;br /&gt;
**pdforientation: Set L for Landscape or P for portrait format&lt;br /&gt;
*&#039;&#039;&#039;$showsgqacode:&#039;&#039;&#039; {{NewIn|1.91}} This setting is used at the printable survey feature {IMG(attId=&amp;quot;78&amp;quot;,height=&amp;quot;16&amp;quot;,width=&amp;quot;16&amp;quot;)} and defaults to &#039;&#039;false&#039;&#039;. If you set &#039;&#039;showsgqacode = true;&#039;&#039; the IDs for 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;
*{IMG(attId=&amp;quot;79&amp;quot;,height=&amp;quot;200&amp;quot;,width=&amp;quot;400&amp;quot;)}&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;
In LimeSurvey 2.05 authentication will be handled by plugins. Because of this the information below might be outdated. See [[Plugins]] for most up to date information.&lt;br /&gt;
&lt;br /&gt;
== Delegate Authentication 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 Webserver software to use this external authentication system, and then ask LimeSurvey to trust the user identity reported by the webserver. In order to enable this feature you have to:&lt;br /&gt;
* set &#039;&#039;&#039;auth_webserver&#039;&#039;&#039; to true in config.php&lt;br /&gt;
* enable authentication at the webserver 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 webserver 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 however than &amp;lt;u&amp;gt;by default Authentication Delegation doesn&#039;t bypass the LimeSurvey authorization system&amp;lt;/u&amp;gt;: this means 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 survey resources.&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 webserver&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 huge user database, it is sometimes easier to auto-import user in the LimeSurvey database.&lt;br /&gt;
*&#039;&#039;&#039;auth_webserver_autocreate_user&#039;&#039;&#039;: if set to true LimeSurvey will try to autoimport users authenticated by the webserver but not already in its users&#039; 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 fake First and Last name, email, 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 an LDAP directory), the true First&amp;amp;Last; names and email of a particular user. You can even customize his privileges on the system based on his groups on the external DB.&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  &#039;&#039;&#039;$WebserverAuth_autouserprofile&#039;&#039;&#039;&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;
== 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 case 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; username defined in your external authentication database. Then in order to login to LimeSurvey as admin, you&#039;ll have to map your external username let&#039;s call it &#039;myname&#039; to the admin login name ine 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;$config[&#039;auth_webserver_user_map&#039;] = Array (&#039;myname&#039; =&amp;gt; &#039;admin&#039;);&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 password to the webserver, 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:58--&amp;gt;&lt;br /&gt;
{{FeatureStarting|1.81}} &lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:59--&amp;gt;&lt;br /&gt;
A user can call the limesurvey login at /limesurvey/admin and pass username and a 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 (&#039;&#039;&#039;use_one_time_passwords&#039;&#039;&#039; =&amp;gt; true) to enable the usage of one time passwords (default = false). More information can be found at [[Manage users#Use one-time passwords|&amp;quot;Manage Users&amp;quot;]].&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;If possible do no touch these settings. Additionally these settings can only be adjusted on config-defaults.php.&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;&#039;$homeurl:&#039;&#039;&#039; This should be set to the URL location of your administration scripts. These are the scripts 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 - {$_SERVER&amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;&#039;SERVER_NAME&#039;]}. 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).&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 a directory 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 installed initially. You may, however, prefer to move these images to another location and if so 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 - {$_SERVER&amp;lt;nowiki&amp;gt;[&amp;lt;/nowiki&amp;gt;&#039;DOCUMENT_ROOT&#039;]}. 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;$fckeditordir:&#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; Directory with the tcpdf.php extensiontcpdf.php&lt;br /&gt;
*&#039;&#039;&#039;$pdffonts:&#039;&#039;&#039; Directory for the TCPDF fonts&lt;br /&gt;
&amp;lt;/translate&amp;gt;&lt;/div&gt;</summary>
		<author><name>Mdekker</name></author>
	</entry>
	<entry>
		<id>https://www.limesurvey.org/manual/index.php?title=Plugins_-_advanced&amp;diff=57511</id>
		<title>Plugins - advanced</title>
		<link rel="alternate" type="text/html" href="https://www.limesurvey.org/manual/index.php?title=Plugins_-_advanced&amp;diff=57511"/>
		<updated>2013-10-08T07:53:15Z</updated>

		<summary type="html">&lt;p&gt;Mdekker: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
Starting from LimeSurvey 2.05, LimeSurvey will officially support plugins. Some plugins will be supported by the LimeSurvey team and will go into core. Some will be supported by others outside the LimeSurvey team. To help find them, check out the [[Available third party plugins]] and add your own plugin to it!&lt;br /&gt;
&lt;br /&gt;
Plugins allow users to customize the functionality of their installation while still being able to benefit from regular software updates.&lt;br /&gt;
&lt;br /&gt;
This documentation is meant for developers that are extending LimeSurvey for their own use or for their clients; end users will not be helped by this documentation.&lt;br /&gt;
&lt;br /&gt;
Plugins must implement the [https://github.com/LimeSurvey/LimeSurvey/blob/2.05/application/libraries/PluginManager/iPlugin.php iPlugin] interface. We recommend extending your plugin class from the [https://github.com/LimeSurvey/LimeSurvey/blob/2.05/application/libraries/PluginManager/PluginBase.php PluginBase] class.&lt;br /&gt;
&lt;br /&gt;
By extending you benefit from common functionality required by plugins that we already have implemented for you. One of these function is the implementation of the getPluginSettings function. This function must return an array describing the configuration options for the user.&lt;br /&gt;
&lt;br /&gt;
The example plugin exposes just 1 configurable setting, the message it&#039;ll show.&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;
protected $settings = array(&lt;br /&gt;
    &#039;logo&#039; =&amp;gt; array(&lt;br /&gt;
          &#039;type&#039; =&amp;gt; &#039;logo&#039;,&lt;br /&gt;
          &#039;path&#039; =&amp;gt; &#039;assets/logo.png&#039;&lt;br /&gt;
     ),&lt;br /&gt;
&lt;br /&gt;
     &#039;message&#039; =&amp;gt; array(&lt;br /&gt;
          &#039;type&#039; =&amp;gt; &#039;string&#039;,&lt;br /&gt;
          &#039;label&#039; =&amp;gt; &#039;Message&#039;&lt;br /&gt;
     )&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The array contains a name for each setting as a key. The values are arrays containing the required meta data.&lt;br /&gt;
&lt;br /&gt;
Supported types are:&lt;br /&gt;
&lt;br /&gt;
* logo&lt;br /&gt;
* string&lt;br /&gt;
* html&lt;br /&gt;
* choice&lt;br /&gt;
* relevance&lt;br /&gt;
&lt;br /&gt;
Besides type a number of other keys are available:&lt;br /&gt;
&lt;br /&gt;
* label, defines a label (use English, the label specified here will be passed through the translation functions)&lt;br /&gt;
* default, defines a value to show if no value is specified.&lt;br /&gt;
* current, defines the current value.&lt;br /&gt;
* readOnly, specifies the setting is read only.&lt;br /&gt;
&lt;br /&gt;
Plugins subscribe to events and can interact with LimeSurvey when the event is fired. For a list of currently available events check [[Plugin events]].&lt;br /&gt;
&lt;br /&gt;
== Special plugins ==&lt;br /&gt;
[[Authentication plugins]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Development]]&lt;br /&gt;
[[Category:Plugins]]&lt;/div&gt;</summary>
		<author><name>Mdekker</name></author>
	</entry>
	<entry>
		<id>https://www.limesurvey.org/manual/index.php?title=Plugin_events&amp;diff=57510</id>
		<title>Plugin events</title>
		<link rel="alternate" type="text/html" href="https://www.limesurvey.org/manual/index.php?title=Plugin_events&amp;diff=57510"/>
		<updated>2013-10-08T07:48:43Z</updated>

		<summary type="html">&lt;p&gt;Mdekker: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;At version 2.05RC1 the following events are available for plugins to subscribe to:&lt;br /&gt;
*afterAdminMenuLoad&lt;br /&gt;
*[[Authentication plugins|afterLoginFormSubmit]]&lt;br /&gt;
*[[Authentication plugins|afterLogout]]&lt;br /&gt;
*afterPluginLoad&lt;br /&gt;
*afterSurveyComplete&lt;br /&gt;
*beforeActivate&lt;br /&gt;
*beforeDeactivate&lt;br /&gt;
*[[Authentication plugins|beforeLogin]]&lt;br /&gt;
*[[Authentication plugins|beforeLogout]]&lt;br /&gt;
*beforePermissionSetSave&lt;br /&gt;
*beforeSurveySettings&lt;br /&gt;
*listExportOptions&lt;br /&gt;
*listExportPlugins&lt;br /&gt;
*listQuestionPlugins&lt;br /&gt;
*newDirectRequest&lt;br /&gt;
*newExport&lt;br /&gt;
*[[Authentication plugins|newLoginForm]]&lt;br /&gt;
*newSurveySettings&lt;br /&gt;
*[[Authentication plugins|newUserSession]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Development]]&lt;br /&gt;
[[Category:Plugins]]&lt;/div&gt;</summary>
		<author><name>Mdekker</name></author>
	</entry>
	<entry>
		<id>https://www.limesurvey.org/manual/index.php?title=Plugin_events&amp;diff=57509</id>
		<title>Plugin events</title>
		<link rel="alternate" type="text/html" href="https://www.limesurvey.org/manual/index.php?title=Plugin_events&amp;diff=57509"/>
		<updated>2013-10-08T07:47:22Z</updated>

		<summary type="html">&lt;p&gt;Mdekker: Created page with &amp;quot;At version 2.05RC1 the following events are available for plugins to subscribe to: *afterAdminMenuLoad *afterLoginFormSubmit *afterLogout *afterPluginLoad *afterSurveyComplete...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;At version 2.05RC1 the following events are available for plugins to subscribe to:&lt;br /&gt;
*afterAdminMenuLoad&lt;br /&gt;
*afterLoginFormSubmit&lt;br /&gt;
*afterLogout&lt;br /&gt;
*afterPluginLoad&lt;br /&gt;
*afterSurveyComplete&lt;br /&gt;
*beforeActivate&lt;br /&gt;
*beforeDeactivate&lt;br /&gt;
*beforeLogin&lt;br /&gt;
*beforeLogout&lt;br /&gt;
*beforePermissionSetSave&lt;br /&gt;
*beforeSurveySettings&lt;br /&gt;
*listExportOptions&lt;br /&gt;
*listExportPlugins&lt;br /&gt;
*listQuestionPlugins&lt;br /&gt;
*newDirectRequest&lt;br /&gt;
*newExport&lt;br /&gt;
*newLoginForm&lt;br /&gt;
*newSurveySettings&lt;br /&gt;
*newUserSession&lt;br /&gt;
&lt;br /&gt;
[[Category:Development]]&lt;br /&gt;
[[Category:Plugins]]&lt;/div&gt;</summary>
		<author><name>Mdekker</name></author>
	</entry>
	<entry>
		<id>https://www.limesurvey.org/manual/index.php?title=Plugins_-_advanced&amp;diff=57508</id>
		<title>Plugins - advanced</title>
		<link rel="alternate" type="text/html" href="https://www.limesurvey.org/manual/index.php?title=Plugins_-_advanced&amp;diff=57508"/>
		<updated>2013-10-08T07:44:22Z</updated>

		<summary type="html">&lt;p&gt;Mdekker: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
Starting from LimeSurvey 2.05, LimeSurvey will officially support plugins.&lt;br /&gt;
&lt;br /&gt;
Plugins allow users to customize the functionality of their installation while still being able to benefit from regular software updates.&lt;br /&gt;
&lt;br /&gt;
This documentation is meant for developers that are extending LimeSurvey for their own use or for their clients; end users will not be helped by this documentation.&lt;br /&gt;
&lt;br /&gt;
Plugins must implement the [https://github.com/LimeSurvey/LimeSurvey/blob/2.05/application/libraries/PluginManager/iPlugin.php iPlugin] interface. We recommend extending your plugin class from the [https://github.com/LimeSurvey/LimeSurvey/blob/2.05/application/libraries/PluginManager/PluginBase.php PluginBase] class.&lt;br /&gt;
&lt;br /&gt;
By extending you benefit from common functionality required by plugins that we already have implemented for you. One of these function is the implementation of the getPluginSettings function. This function must return an array describing the configuration options for the user.&lt;br /&gt;
&lt;br /&gt;
The example plugin exposes just 1 configurable setting, the message it&#039;ll show.&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;
protected $settings = array(&lt;br /&gt;
    &#039;logo&#039; =&amp;gt; array(&lt;br /&gt;
          &#039;type&#039; =&amp;gt; &#039;logo&#039;,&lt;br /&gt;
          &#039;path&#039; =&amp;gt; &#039;assets/logo.png&#039;&lt;br /&gt;
     ),&lt;br /&gt;
&lt;br /&gt;
     &#039;message&#039; =&amp;gt; array(&lt;br /&gt;
          &#039;type&#039; =&amp;gt; &#039;string&#039;,&lt;br /&gt;
          &#039;label&#039; =&amp;gt; &#039;Message&#039;&lt;br /&gt;
     )&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The array contains a name for each setting as a key. The values are arrays containing the required meta data.&lt;br /&gt;
&lt;br /&gt;
Supported types are:&lt;br /&gt;
&lt;br /&gt;
* logo&lt;br /&gt;
* string&lt;br /&gt;
* html&lt;br /&gt;
* choice&lt;br /&gt;
* relevance&lt;br /&gt;
&lt;br /&gt;
Besides type a number of other keys are available:&lt;br /&gt;
&lt;br /&gt;
* label, defines a label (use English, the label specified here will be passed through the translation functions)&lt;br /&gt;
* default, defines a value to show if no value is specified.&lt;br /&gt;
* current, defines the current value.&lt;br /&gt;
* readOnly, specifies the setting is read only.&lt;br /&gt;
&lt;br /&gt;
Plugins subscribe to events and can interact with LimeSurvey when the event is fired. For a list of currently available events check [[Plugin events]].&lt;br /&gt;
&lt;br /&gt;
== Special plugins ==&lt;br /&gt;
[[Authentication plugins]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Development]]&lt;br /&gt;
[[Category:Plugins]]&lt;/div&gt;</summary>
		<author><name>Mdekker</name></author>
	</entry>
	<entry>
		<id>https://www.limesurvey.org/manual/index.php?title=Plugins_-_advanced&amp;diff=57507</id>
		<title>Plugins - advanced</title>
		<link rel="alternate" type="text/html" href="https://www.limesurvey.org/manual/index.php?title=Plugins_-_advanced&amp;diff=57507"/>
		<updated>2013-10-08T07:43:50Z</updated>

		<summary type="html">&lt;p&gt;Mdekker: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
Starting from LimeSurvey 2.05, LimeSurvey will officially support plugins.&lt;br /&gt;
&lt;br /&gt;
Plugins allow users to customize the functionality of their installation while still being able to benefit from regular software updates.&lt;br /&gt;
&lt;br /&gt;
This documentation is meant for developers that are extending LimeSurvey for their own use or for their clients; end users will not be helped by this documentation.&lt;br /&gt;
&lt;br /&gt;
Plugins must implement the [https://github.com/LimeSurvey/LimeSurvey/blob/2.05/application/libraries/PluginManager/iPlugin.php iPlugin] interface. We recommend extending your plugin class from the [https://github.com/LimeSurvey/LimeSurvey/blob/2.05/application/libraries/PluginManager/PluginBase.php PluginBase] class.&lt;br /&gt;
&lt;br /&gt;
By extending you benefit from common functionality required by plugins that we already have implemented for you. One of these function is the implementation of the getPluginSettings function. This function must return an array describing the configuration options for the user.&lt;br /&gt;
&lt;br /&gt;
The example plugin exposes just 1 configurable setting, the message it&#039;ll show.&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;
protected $settings = array(&lt;br /&gt;
    &#039;logo&#039; =&amp;gt; array(&lt;br /&gt;
          &#039;type&#039; =&amp;gt; &#039;logo&#039;,&lt;br /&gt;
          &#039;path&#039; =&amp;gt; &#039;assets/logo.png&#039;&lt;br /&gt;
     ),&lt;br /&gt;
&lt;br /&gt;
     &#039;message&#039; =&amp;gt; array(&lt;br /&gt;
          &#039;type&#039; =&amp;gt; &#039;string&#039;,&lt;br /&gt;
          &#039;label&#039; =&amp;gt; &#039;Message&#039;&lt;br /&gt;
     )&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The array contains a name for each setting as a key. The values are arrays containing the required meta data.&lt;br /&gt;
&lt;br /&gt;
Supported types are:&lt;br /&gt;
&lt;br /&gt;
* logo&lt;br /&gt;
* string&lt;br /&gt;
* html&lt;br /&gt;
* choice&lt;br /&gt;
* relevance&lt;br /&gt;
&lt;br /&gt;
Besides type a number of other keys are available:&lt;br /&gt;
&lt;br /&gt;
* label, defines a label (use English, the label specified here will be passed through the translation functions)&lt;br /&gt;
* default, defines a value to show if no value is specified.&lt;br /&gt;
* current, defines the current value.&lt;br /&gt;
* readOnly, specifies the setting is read only.&lt;br /&gt;
&lt;br /&gt;
Plugins subscribe to events and can interact with LimeSurvey when the event is fired. For a list of currently available events check [Plugin events].&lt;br /&gt;
&lt;br /&gt;
== Special plugins ==&lt;br /&gt;
[[Authentication plugins]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Development]]&lt;br /&gt;
[[Category:Plugins]]&lt;/div&gt;</summary>
		<author><name>Mdekker</name></author>
	</entry>
	<entry>
		<id>https://www.limesurvey.org/manual/index.php?title=Available_third_party_plugins&amp;diff=57506</id>
		<title>Available third party plugins</title>
		<link rel="alternate" type="text/html" href="https://www.limesurvey.org/manual/index.php?title=Available_third_party_plugins&amp;diff=57506"/>
		<updated>2013-10-08T07:38:43Z</updated>

		<summary type="html">&lt;p&gt;Mdekker: Created page with &amp;quot;If you have a plugin you would like to share with the world, feel free to add it to this page.  == Authentication plugins == *[https://github.com/pitbulk/limesurvey-saml SAML ...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;If you have a plugin you would like to share with the world, feel free to add it to this page.&lt;br /&gt;
&lt;br /&gt;
== Authentication plugins ==&lt;br /&gt;
*[https://github.com/pitbulk/limesurvey-saml SAML support] by Sixto Martin Garcia&lt;br /&gt;
&lt;br /&gt;
[[Category:Plugins]]&lt;/div&gt;</summary>
		<author><name>Mdekker</name></author>
	</entry>
	<entry>
		<id>https://www.limesurvey.org/manual/index.php?title=LimeSurvey_Manual&amp;diff=57505</id>
		<title>LimeSurvey Manual</title>
		<link rel="alternate" type="text/html" href="https://www.limesurvey.org/manual/index.php?title=LimeSurvey_Manual&amp;diff=57505"/>
		<updated>2013-10-08T07:36:13Z</updated>

		<summary type="html">&lt;p&gt;Mdekker: &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;
=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;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;
*[[Optional settings]]&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;
[http://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 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, and to look in our [http://www.limesurvey.org/en/forum/ discussion forums].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:7--&amp;gt;&lt;br /&gt;
Remember that [http://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 [http://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;
***[[Upgrade hints for version 1.92]]&lt;br /&gt;
**[[Transferring an installation]]&lt;br /&gt;
**[[Installation FAQ]]&lt;br /&gt;
**[[Installation security hints]]&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;
*[[Getting Started]]&lt;br /&gt;
**[[First login - Your user preferences]]&lt;br /&gt;
*[[Creating surveys - Introduction]]&lt;br /&gt;
**[[Creating a new survey]]&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 HowTos]]&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;
**[[Validate Survey Logic]]&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;
**[[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;
***[[Excel Survey Structure]]&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;
**[[RemoteControl 2 API]]&lt;br /&gt;
**[[Authentication vs Atlassian Crowd]]&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 1.x development documentation]]&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 1.x/2.x]]&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 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>Mdekker</name></author>
	</entry>
	<entry>
		<id>https://www.limesurvey.org/manual/index.php?title=Authentication_plugins&amp;diff=57504</id>
		<title>Authentication plugins</title>
		<link rel="alternate" type="text/html" href="https://www.limesurvey.org/manual/index.php?title=Authentication_plugins&amp;diff=57504"/>
		<updated>2013-10-08T07:34:12Z</updated>

		<summary type="html">&lt;p&gt;Mdekker: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;An authentication plugin has some additional requirements over a regular plugin. Here we list the requirements.&lt;br /&gt;
&lt;br /&gt;
To make creating your own authentication plugin easier, you should extend the abstract [https://github.com/LimeSurvey/LimeSurvey/blob/2.05/application/libraries/PluginManager/AuthPluginBase.php AuthPluginBase] class.&lt;br /&gt;
&lt;br /&gt;
To get an idea of the possibilities, check out the three core authentication plugins (check their pages for more information about configuration options):&lt;br /&gt;
* [https://github.com/LimeSurvey/LimeSurvey/blob/2.05/application/core/plugins/Authdb/Authdb.php Authdb] Database authentication - this is the default method for all new LimeSurvey installations&lt;br /&gt;
* [https://github.com/LimeSurvey/LimeSurvey/blob/2.05/application/core/plugins/Authwebserver/Authwebserver.php Authwebserver] Webserver authentication - This one skips the login form, and provides methods for user creation&lt;br /&gt;
* [https://github.com/LimeSurvey/LimeSurvey/blob/2.05/application/core/plugins/AuthLDAP/AuthLDAP.php AuthLDAP] LDAP authentication - Adds a custom error message and relies on a user being present in the LimeSurvey database.&lt;br /&gt;
&lt;br /&gt;
There are 6 events you can subscribe to:&lt;br /&gt;
&lt;br /&gt;
== beforeLogin ==&lt;br /&gt;
This is called first, and can possibly disable the loginform, for example when webserver authentication is used and we trust on that. To do this, use &#039;&#039;$this-&amp;gt;setAuthPlugin()&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== newLoginForm ==&lt;br /&gt;
Here you can add your own elements to the form. You should add your username/password elements, but could also add a domain selector or anything else you need. This will only be shown when the selected authentication method was chosen on the selector that is added when more then one plugin is present. When your authentication plugin does not need a form, and can not be selected as an option (like webserver authentication) you should not add a form element here.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$this-&amp;gt;getEvent()                  // Get the current event&lt;br /&gt;
     -&amp;gt;getContent($this)           // Get the content for this plugin&lt;br /&gt;
     -&amp;gt;addContent(CHtml::tag(      // And add some content to it&lt;br /&gt;
         &#039;li&#039;, &lt;br /&gt;
         array(), &lt;br /&gt;
         &amp;quot;&amp;lt;label for=&#039;user&#039;&amp;gt;&amp;quot;  . gT(&amp;quot;Username&amp;quot;) . &amp;quot;&amp;lt;/label&amp;gt;&amp;lt;input name=&#039;user&#039; id=&#039;user&#039; type=&#039;text&#039; size=&#039;40&#039; maxlength=&#039;40&#039; value=&#039;&#039; /&amp;gt;&amp;quot;))&lt;br /&gt;
     -&amp;gt;addContent(CHtml::tag(&lt;br /&gt;
         &#039;li&#039;, &lt;br /&gt;
         array(), &lt;br /&gt;
         &amp;quot;&amp;lt;label for=&#039;password&#039;&amp;gt;&amp;quot;  . gT(&amp;quot;Password&amp;quot;) . &amp;quot;&amp;lt;/label&amp;gt;&amp;lt;input name=&#039;password&#039; id=&#039;password&#039; type=&#039;password&#039; size=&#039;40&#039; maxlength=&#039;40&#039; value=&#039;&#039; /&amp;gt;&amp;quot;));&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== afterLoginFormSubmit ==&lt;br /&gt;
When the form for this plugin was submitted, this event is called. Here you can handle setting the values to the plugin. This event is also called when there was no form submitted and form display was canceled in the beforeLogin event.&lt;br /&gt;
&lt;br /&gt;
== newUserSession ==&lt;br /&gt;
This is where the real authentication takes place. You should use $this-&amp;gt;setAuthSuccess($oUser) for a successful attempt and provide a User object. If you fail to do so it will result in an authentication failure. If you need to provide a message about why the authentication failed, you can do so by using $this-&amp;gt;setAuthFailure($code, $message) where code is any code other than 0. The code is not used at this moment. The message should be a message in English, localised using the available tools in the plugin api. See the general plugin documenation for more information about that topic.&lt;br /&gt;
&lt;br /&gt;
== beforeLogout ==&lt;br /&gt;
This is fired before the user is destroyed and the session regenerated. This is the time for cleanup / logout in external systems if needed.&lt;br /&gt;
&lt;br /&gt;
== afterLogout ==&lt;br /&gt;
When the user is destroyed, you might want to redirect to a different page then currently defined. This is the right place to do so.&lt;br /&gt;
&lt;br /&gt;
[[Category:Plugins]]&lt;/div&gt;</summary>
		<author><name>Mdekker</name></author>
	</entry>
	<entry>
		<id>https://www.limesurvey.org/manual/index.php?title=Plugins_-_advanced&amp;diff=57503</id>
		<title>Plugins - advanced</title>
		<link rel="alternate" type="text/html" href="https://www.limesurvey.org/manual/index.php?title=Plugins_-_advanced&amp;diff=57503"/>
		<updated>2013-10-08T07:30:24Z</updated>

		<summary type="html">&lt;p&gt;Mdekker: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
Starting from LimeSurvey 2.05, LimeSurvey will officially support plugins.&lt;br /&gt;
&lt;br /&gt;
Plugins allow users to customize the functionality of their installation while still being able to benefit from regular software updates.&lt;br /&gt;
&lt;br /&gt;
This documentation is meant for developers that are extending LimeSurvey for their own use or for their clients; end users will not be helped by this documentation.&lt;br /&gt;
&lt;br /&gt;
Plugins must implement the [https://github.com/LimeSurvey/LimeSurvey/blob/2.05/application/libraries/PluginManager/iPlugin.php iPlugin] interface. We recommend extending your plugin class from the [https://github.com/LimeSurvey/LimeSurvey/blob/2.05/application/libraries/PluginManager/PluginBase.php PluginBase] class.&lt;br /&gt;
&lt;br /&gt;
By extending you benefit from common functionality required by plugins that we already have implemented for you. One of these function is the implementation of the getPluginSettings function. This function must return an array describing the configuration options for the user.&lt;br /&gt;
&lt;br /&gt;
The example plugin exposes just 1 configurable setting, the message it&#039;ll show.&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;
protected $settings = array(&lt;br /&gt;
    &#039;logo&#039; =&amp;gt; array(&lt;br /&gt;
          &#039;type&#039; =&amp;gt; &#039;logo&#039;,&lt;br /&gt;
          &#039;path&#039; =&amp;gt; &#039;assets/logo.png&#039;&lt;br /&gt;
     ),&lt;br /&gt;
&lt;br /&gt;
     &#039;message&#039; =&amp;gt; array(&lt;br /&gt;
          &#039;type&#039; =&amp;gt; &#039;string&#039;,&lt;br /&gt;
          &#039;label&#039; =&amp;gt; &#039;Message&#039;&lt;br /&gt;
     )&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The array contains a name for each setting as a key. The values are arrays containing the required meta data.&lt;br /&gt;
&lt;br /&gt;
Supported types are:&lt;br /&gt;
&lt;br /&gt;
* logo&lt;br /&gt;
* string&lt;br /&gt;
* html&lt;br /&gt;
* choice&lt;br /&gt;
* relevance&lt;br /&gt;
&lt;br /&gt;
Besides type a number of other keys are available:&lt;br /&gt;
&lt;br /&gt;
* label, defines a label (use English, the label specified here will be passed through the translation functions)&lt;br /&gt;
* default, defines a value to show if no value is specified.&lt;br /&gt;
* current, defines the current value.&lt;br /&gt;
* readOnly, specifies the setting is read only.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Special plugins ==&lt;br /&gt;
[[Authentication plugins]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Development]]&lt;br /&gt;
[[Category:Plugins]]&lt;/div&gt;</summary>
		<author><name>Mdekker</name></author>
	</entry>
	<entry>
		<id>https://www.limesurvey.org/manual/index.php?title=Development_overview&amp;diff=56147</id>
		<title>Development overview</title>
		<link rel="alternate" type="text/html" href="https://www.limesurvey.org/manual/index.php?title=Development_overview&amp;diff=56147"/>
		<updated>2013-09-04T09:41:34Z</updated>

		<summary type="html">&lt;p&gt;Mdekker: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
Table of contents:&lt;br /&gt;
&lt;br /&gt;
*[[LimeSurvey roadmap]]&lt;br /&gt;
*[[The LimeSurvey project team]]&lt;br /&gt;
*[[How to join the LimeSurvey project team]]&lt;br /&gt;
**[[How to become a LimeSurvey Developer]]&lt;br /&gt;
*[[Accessing the source code]]&lt;br /&gt;
**[[Switch from Subversion to Git]]&lt;br /&gt;
*[[Coding guidelines]]&lt;br /&gt;
*[[How to document your source code]]&lt;br /&gt;
*[[Standard for Git commit messages]]&lt;br /&gt;
*[[Updating FCKEditor]]&lt;br /&gt;
*[[Release process]]&lt;br /&gt;
*[[Help us: Tasks]]&lt;br /&gt;
*[[How can I support LimeSurvey?]]&lt;br /&gt;
*[[Developer user pages]]&lt;br /&gt;
**[[User:c_schmitz]]&lt;br /&gt;
**[[User:jcleeland]]&lt;br /&gt;
**[[User:kadejo]]&lt;br /&gt;
**[[User:Mazi]]&lt;br /&gt;
**[[User:Mdekker]]&lt;br /&gt;
**[[User:Shnoulle]]&lt;br /&gt;
**[[User:magiclko]]&lt;br /&gt;
***[[SurveyPress]]&lt;br /&gt;
*[[How to contribute new features]]&lt;br /&gt;
*[[Database versioning]]&lt;br /&gt;
*[[The bugtracker and git]]&lt;br /&gt;
*[[Plugin system architecture]]&lt;br /&gt;
**[[Authentication_plugins]]&lt;br /&gt;
**[[Question plugins]]&lt;br /&gt;
***[[Creating a question plugin]]&lt;br /&gt;
****[[Question signature]]&lt;br /&gt;
**[[Defining attributes]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Development]]&lt;/div&gt;</summary>
		<author><name>Mdekker</name></author>
	</entry>
	<entry>
		<id>https://www.limesurvey.org/manual/index.php?title=Development_overview&amp;diff=56143</id>
		<title>Development overview</title>
		<link rel="alternate" type="text/html" href="https://www.limesurvey.org/manual/index.php?title=Development_overview&amp;diff=56143"/>
		<updated>2013-09-04T09:38:35Z</updated>

		<summary type="html">&lt;p&gt;Mdekker: Added authentication plugins, shouldn&amp;#039;t this page be just the development category?&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
Table of contents:&lt;br /&gt;
&lt;br /&gt;
*[[LimeSurvey roadmap]]&lt;br /&gt;
*[[The LimeSurvey project team]]&lt;br /&gt;
*[[How to join the LimeSurvey project team]]&lt;br /&gt;
**[[How to become a LimeSurvey Developer]]&lt;br /&gt;
*[[Accessing the source code]]&lt;br /&gt;
**[[Switch from Subversion to Git]]&lt;br /&gt;
*[[Coding guidelines]]&lt;br /&gt;
*[[How to document your source code]]&lt;br /&gt;
*[[Standard for Git commit messages]]&lt;br /&gt;
*[[Updating FCKEditor]]&lt;br /&gt;
*[[Release process]]&lt;br /&gt;
*[[Help us: Tasks]]&lt;br /&gt;
*[[How can I support LimeSurvey?]]&lt;br /&gt;
*[[Developer user pages]]&lt;br /&gt;
**[[User:c_schmitz]]&lt;br /&gt;
**[[User:jcleeland]]&lt;br /&gt;
**[[User:kadejo]]&lt;br /&gt;
**[[User:Mazi]]&lt;br /&gt;
**[[User:Shnoulle]]&lt;br /&gt;
**[[User:magiclko]]&lt;br /&gt;
***[[SurveyPress]]&lt;br /&gt;
*[[How to contribute new features]]&lt;br /&gt;
*[[Database versioning]]&lt;br /&gt;
*[[The bugtracker and git]]&lt;br /&gt;
*[[Plugin system architecture]]&lt;br /&gt;
**[[Authentication_plugins]]&lt;br /&gt;
**[[Question plugins]]&lt;br /&gt;
***[[Creating a question plugin]]&lt;br /&gt;
****[[Question signature]]&lt;br /&gt;
**[[Defining attributes]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Development]]&lt;/div&gt;</summary>
		<author><name>Mdekker</name></author>
	</entry>
	<entry>
		<id>https://www.limesurvey.org/manual/index.php?title=Workarounds:_Question_design,_layout_and_templating&amp;diff=44574</id>
		<title>Workarounds: Question design, layout and templating</title>
		<link rel="alternate" type="text/html" href="https://www.limesurvey.org/manual/index.php?title=Workarounds:_Question_design,_layout_and_templating&amp;diff=44574"/>
		<updated>2013-07-08T14:24:22Z</updated>

		<summary type="html">&lt;p&gt;Mdekker: /* Multiple question types in array */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
This section more or less deals with styling your survey, adjusting the layout and setting up special question types. You can find &#039;&#039;&#039;similar information&#039;&#039;&#039; at these pages:&lt;br /&gt;
* [[The template editor]]&lt;br /&gt;
* [[Workarounds: Manipulating a survey at runtime using Javascript]]&lt;br /&gt;
* [[Workarounds: Survey behaviour]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;simplebox&amp;quot;&amp;gt;&amp;lt;center&amp;gt;&amp;lt;br /&amp;gt;&#039;&#039;&#039;Please keep in mind that these workarounds are not official LimeSurvey extensions - they are solutions that users have created for themselves.&amp;lt;br /&amp;gt;&amp;lt;span style=&#039;color:#EE0000,#FFFFFF&#039;&amp;gt;Therefore LimeSurvey can&#039;t offer guarantees or support for these solutions.&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;If you have questions, please contact the users that, thankfully, shared their solutions with the community.&#039;&#039;&#039;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;/center&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
=Getting rid of the question mark symbol (help.gif)=&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Tested with: 1.80+ (6536)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
To get rid of the question mark symbol that LimeSurvey displays at the end of a question, you can either upload an empty help.gif into the template folder (as discussed in the forum) or you can use the Template editor: Open the &#039;&#039;template.css&#039;&#039; of your template and search for &#039;&#039;div.questionhelp img&#039;&#039;, then add a &#039;&#039;visibility:hidden;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
It will look something like this:&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;
div.questionhelp img&lt;br /&gt;
&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
  margin:5px;&lt;br /&gt;
&lt;br /&gt;
  visibility:hidden;&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also &#039;&#039;&#039;replace the image&#039;&#039;&#039; by following [[The template editor#Replacing the help icon|these instructions]].&lt;br /&gt;
&lt;br /&gt;
=Require users to check a box agreeing to privacy statement before registering for a survey=&lt;br /&gt;
&lt;br /&gt;
If you need to have users positively acknowledge a privacy statement before submitting a registration form, the following will help you do this.&lt;br /&gt;
&lt;br /&gt;
It involves a minor modification to common.php in versions up to 1.85. Later versions may not require this.&lt;br /&gt;
&lt;br /&gt;
Edit common.php and look for the line (at approximately line 3014)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;$registerform .= &amp;quot;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;input class=&#039;submit&#039; type=&#039;submit&#039; value=&#039;&amp;quot;.$clang-&amp;gt;gT(&amp;quot;Continue&amp;quot;).&amp;quot;&#039; /&amp;gt;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
and change it to:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;$registerform .= &amp;quot;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;input id=&#039;registercontinue&#039; class=&#039;submit&#039; type=&#039;submit&#039; value=&#039;&amp;quot;.$clang-&amp;gt;gT(&amp;quot;Continue&amp;quot;).&amp;quot;&#039; /&amp;gt;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then save common.php. This gives you DOM access to the &amp;quot;continue&amp;quot; button on the register form, but will have no other practical effect or change to LimeSurvey&#039;s operations.&lt;br /&gt;
&lt;br /&gt;
Next, you need to edit the template you are using (see the documentation on the Template editor if you don&#039;t know how to do this).&lt;br /&gt;
&lt;br /&gt;
In the template editor, open the screen &amp;quot;Register page&amp;quot; and select the file &amp;quot;register.pstpl&amp;quot;&lt;br /&gt;
&lt;br /&gt;
There are two modifications you need to make to this file. The first is to add the following code after the line that says &#039;&#039;{REGISTERFORM}&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&amp;lt;script type=&#039;text/javascript&#039;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/script&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This code disables the &amp;quot;Continue&amp;quot; button so that nobody can process the registration form until they&#039;ve clicked the checkbox.&lt;br /&gt;
&lt;br /&gt;
The second modification to make is to be done between the lines {REGISTERMESSAGE2} and {REGISTERFORM}. Add:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&amp;lt;center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;label&amp;gt; Accept&lt;br /&gt;
&lt;br /&gt;
   &amp;lt;input type=&#039;radio&#039;&lt;br /&gt;
&lt;br /&gt;
          name=&amp;quot;privacy&amp;quot;&lt;br /&gt;
&lt;br /&gt;
          value=&amp;quot;YES&amp;quot;&lt;br /&gt;
&lt;br /&gt;
          onChange=&amp;quot;if(this.checked) {&lt;br /&gt;
&lt;br /&gt;
                      document.getElementById(&#039;registercontinue&#039;).disabled=false;&lt;br /&gt;
&lt;br /&gt;
                    }&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;/label&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;label&amp;gt;I don&#039;t accept&lt;br /&gt;
&lt;br /&gt;
   &amp;lt;input type=&#039;radio&#039;&lt;br /&gt;
&lt;br /&gt;
          name=&amp;quot;privacy&amp;quot;&lt;br /&gt;
&lt;br /&gt;
          value=&amp;quot;NO&amp;quot;&lt;br /&gt;
&lt;br /&gt;
          CHECKED&lt;br /&gt;
&lt;br /&gt;
          onChange=&amp;quot;if(this.checked) {&lt;br /&gt;
&lt;br /&gt;
                      document.getElementById(&#039;registercontinue&#039;).disabled=true;&lt;br /&gt;
&lt;br /&gt;
                    }&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;/label&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/center&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then the users will have to agree to whatever text you replace &amp;quot;Do you agree to privacy stuff?&amp;quot; before they continue on and register.&lt;br /&gt;
&lt;br /&gt;
(Thanks to &#039;&#039;Pippo_Jedi&#039;&#039; for helping work this out)&lt;br /&gt;
&lt;br /&gt;
=Different progress indicator=&lt;br /&gt;
&lt;br /&gt;
==Version 1.87 and later:==&lt;br /&gt;
&lt;br /&gt;
Add the following to the end of template.js. It will find the progress value and insert it into the element following the progress bar.&lt;br /&gt;
&lt;br /&gt;
It should be pointed out that I had to introduce a delay in firing the function because the progress value is not calculated until after template.js is called. The delay is set at 1/10 of a second but you may be able to reduce that.&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;
   // Display progress value&lt;br /&gt;
&lt;br /&gt;
   function setProgValue() {&lt;br /&gt;
&lt;br /&gt;
       var progress = $(&#039;#progressbar&#039;).attr(&#039;aria-valuenow&#039;);&lt;br /&gt;
&lt;br /&gt;
       $(&#039;#progress-post&#039;).text(progress+&#039;%&#039;).show();&lt;br /&gt;
&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   $(document).ready(function(){&lt;br /&gt;
&lt;br /&gt;
       $(&#039;#progress-post&#039;).hide();&lt;br /&gt;
&lt;br /&gt;
       setTimeout(&#039;setProgValue()&#039;,100);&lt;br /&gt;
&lt;br /&gt;
   });&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you want to hide the &amp;quot;0%&amp;quot; before the progress bar, add the following to the end of template.css:&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;
#progress-pre {&lt;br /&gt;
&lt;br /&gt;
   display: none;&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Delete unwanted gaps in question title=&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Tested with: &#039;&#039;&lt;br /&gt;
&lt;br /&gt;
When copying data (questions, answers, ...) from MS Word or other applications into the editor there might occur some gaps in the question title.&lt;br /&gt;
&lt;br /&gt;
There are two solutions to this:&lt;br /&gt;
# Use popup mode and manually delete unwanting extra html tags (requires html knowledge).&lt;br /&gt;
# Disable paste word feature: Tweak your limesurvey-config.js file in limesurvey/admin/scripts/fckeditor.26 and set the following option to true:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;FCKConfig.ForcePasteAsPlainText = true ;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After that clear you browser cache and try again.&lt;br /&gt;
&lt;br /&gt;
=How to change the &amp;lt;font-size&amp;gt; tags using CSS=&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;This workaround was deleted because it is outdated. Such changes can be done by [[The template editor#Styling questions with CSS|adjusting template.css]] of your template.&lt;br /&gt;
&lt;br /&gt;
=Question type variation: Scale with bars (one and two sided)=&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Tested with: &#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Some methodogical issues to think about: Very often a common scale as 1 to 5 or -2 to +2 fits all needs, as the shown subject is clearly defined as positive or negative. As soon as you would reduce the influence from the question and scale on the respondent, you will need something neutral to determine tendences, emphases and so on.&lt;br /&gt;
&lt;br /&gt;
So I put up a new variation of the one and two sided array question:&lt;br /&gt;
&lt;br /&gt;
ttp://www.limesurvey.org/images/fbfiles/images/example_bar_scale.jpg&lt;br /&gt;
&lt;br /&gt;
In my example the left side reads &amp;quot;strategical planning&amp;quot; and the right side &amp;quot;operative business&amp;quot;. None of these are purely negative or positive, so the bars only show in which direction the balancing point moves.&lt;br /&gt;
&lt;br /&gt;
To realize a question as shown above just do as follows:&lt;br /&gt;
&lt;br /&gt;
Set up as many bars as you will need (in my example there are four different bars in total) with a graphic program like PAINT .NET, GIMP or similar ones (yes, you may also use commercial software like Photoshop). To prevent the bars from looking twitchy, designate the size in advance. I did one bar 60x15 px, one 45x15px, one 30x15px and at last 15x15px. Save them as PNG, JPG or GIF.&lt;br /&gt;
# Create a new label set within Lime. Call it whatever you like.&lt;br /&gt;
# Enter a code number at first, then press the pencil symbol to enter the editor.&lt;br /&gt;
#Press the &amp;quot;Insert / edit image&amp;quot; button and upload the bar you want to insert with the FCK upload tool. Then choose the uploaded picture, save and leave the FCK editor.&lt;br /&gt;
#The row in the lable editor now shows an &amp;lt;img&amp;gt;-tag which refers to your bar picture.&lt;br /&gt;
#Repeat the above described steps as often as needed to build up your bar scale.&lt;br /&gt;
&lt;br /&gt;
=Doing a Likert Scale=&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Tested with: &#039;&#039;&lt;br /&gt;
&lt;br /&gt;
A Likert Scale is a special type of the Semantic Differential question where several item shall be rated on different scales, each marked at the beginning and at the end with opposite statements. See example:&lt;br /&gt;
&lt;br /&gt;
http://www.limesurvey.org/images/fbfiles/images/lickert.jpg&lt;br /&gt;
&lt;br /&gt;
To do this in LimeSurvey just follow these steps:&lt;br /&gt;
#Create a label set with values from 0 to 7 (for the classic Likert Scale - feel free to choose other ranges).&lt;br /&gt;
#Create a new question and choose Array (Flexible Labels) as question type.&lt;br /&gt;
#Assign the Likert Scale label set to this question.&lt;br /&gt;
#Enter your answers as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&amp;lt;DIV style=&amp;quot;white-space: nowrap;&amp;quot;&amp;gt;ITEM statement1|statement2&amp;lt;/div&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The white-space style is to avoid line breaks which would ruin the whole scale. feel free to insert non-breakable spaces between the ITEM and statement1 to define the margin between these to strings.&lt;br /&gt;
&lt;br /&gt;
=Alternate background colour of questions=&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Tested with: 1.85+ (7191)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
To alternate the background colour of questions, open the &#039;&#039;template.css&#039;&#039; of your template with the Template Editor or a text editor and modify the &#039;&#039;Question styles&#039;&#039; section to include the following style.&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;
div#question2 td.questiontext,&lt;br /&gt;
&lt;br /&gt;
div#question4 td.questiontext,&lt;br /&gt;
&lt;br /&gt;
div#question6 td.questiontext {&lt;br /&gt;
&lt;br /&gt;
   background-color: #E0EBF8;&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Be sure to apply the style to all of the questions you would like modified using their question IDs (&#039;&#039;question2, question4, question6&#039;&#039; in this case). Question IDs are displayed when creating or editing questions - see below:&lt;br /&gt;
&lt;br /&gt;
[[File:qid_1_493x173.gif]]&lt;br /&gt;
&lt;br /&gt;
Here the question ID is #question80 .&lt;br /&gt;
&lt;br /&gt;
=Embedding audio in questions=&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Tested with: 1.85+ (7191), IE 7, FireFox 3&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Audio clips can be embedded in most question text or answer text. In this example, using the default template, I&#039;ve embedded clips into the answers of an &#039;&#039;&#039;&#039;&#039;Array (Yes/No/Uncertain)&#039;&#039;&#039;&#039;&#039; question to ask respondents how they feel about some sounds. The resulting question will look like this.&lt;br /&gt;
&lt;br /&gt;
[[File:audioTest_595x202.gif]]&lt;br /&gt;
&lt;br /&gt;
It&#039;s accomplished by placing the following code in each of the answers.&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;
&amp;lt;embed height=&amp;quot;20&amp;quot; width=&amp;quot;128&amp;quot; autostart=&amp;quot;false&amp;quot; controls=&amp;quot;console&amp;quot;&lt;br /&gt;
&lt;br /&gt;
loop=&amp;quot;true&amp;quot; volume=&amp;quot;50&amp;quot; src=&amp;quot;{TEMPLATEURL}audio_1.mp3&amp;quot;&amp;gt;&amp;lt;/embed&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Some notes about the code:&lt;br /&gt;
*The &#039;&#039;audio_1.mp3&#039;&#039; part will be different for each answer (it&#039;s the audio file name).&lt;br /&gt;
*In this case the audio files are residing in the template folder being used for this survey (that&#039;s where &#039;&#039;{TEMPLATEURL}&#039;&#039; points to) but they can be placed anywhere if you use an absolute URL in the &#039;&#039;src&#039;&#039; parameter - something like &#039;&#039;src=&amp;quot;http://mysite.com/audio/audio_1.mp3&amp;quot;&#039;&#039;&lt;br /&gt;
*If the audio file doesn&#039;t exist where the &#039;&#039;src&#039;&#039; parameter indicates, the player will not appear.&lt;br /&gt;
*You&#039;ll need to insert the code into the answers using the source screen - click on &amp;quot;Edit answers&amp;quot;, click the pencil beside the text box, click &amp;quot;Source&amp;quot; in the pop-up, enter the code and save it with the little diskette icon.&lt;br /&gt;
*You may need to turn off the XSS filter - see the documentation for [http://docs.limesurvey.org/tiki-index.php?page=Global+settings&amp;amp;structure;=English+Instructions+for+LimeSurvey#Security Global settings].&lt;br /&gt;
&lt;br /&gt;
Although the above example places the audio in the answer text of the question, the same principles can be used to place it in the question text itself. Something like this perhaps.&lt;br /&gt;
&lt;br /&gt;
[[File:audioTest_595x154.gif]]&lt;br /&gt;
&lt;br /&gt;
=Hiding inputs of a &amp;quot;Multiple options with comments&amp;quot; question=&lt;br /&gt;
&lt;br /&gt;
Tested with: 1.85+ (7253), IE 6/7, FireFox 3.0, Safari 3.2, Chrome 2.0&lt;br /&gt;
&lt;br /&gt;
There may be times when you want to hide some of the input boxes of a &#039;&#039;&#039;&#039;&#039;Multiple options with comments&#039;&#039;&#039;&#039;&#039; question as in the image below.&lt;br /&gt;
&lt;br /&gt;
[[File:hidden_inputs_541x168.gif]]&lt;br /&gt;
&lt;br /&gt;
This can be accomplished with CSS (see [[The template editor#Styling questions with CSS|Styling questions in LimeSurvey 1.8]]). For each input that you want to hide, add the following style to your template.css file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;css&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
#answer11111X22X33Acomment {&lt;br /&gt;
   display: none;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Where 11111 is your survey ID, 22 is your group ID, 33 is your question ID and A is the answer code.&lt;br /&gt;
&lt;br /&gt;
Note that you will still see columns for the hidden inputs in your data but they will be empty.&lt;br /&gt;
&lt;br /&gt;
=Multiple question types in array=&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Tested with: 1.90 - 1.92+, IE 7/8/9, Firefox 13, Safari 5, Chrome 10&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note: sample survey works in 2.00+ but code is different from example below. Make sure to use the right code. Copy paste the script from the sample survey adn adapt.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Media:limesurvey_survey_62584.lss|Download the sample survey]]&lt;br /&gt;
&lt;br /&gt;
This workaround allows you to present multiple question types in what appears to be an array - as depicted in the image below and [http://www.partnersinc.biz/surveys//index.php?sid=62584&amp;amp;newtest=Y&amp;amp;lang=en demonstrated here] (download the sample survey - [[Media:limesurvey_survey_62584.lss|limesurvey_survey_62584.lss]]). This example uses the default template but should be adaptable to any template using divisions for question containers.&lt;br /&gt;
&lt;br /&gt;
[[File:inline_questions_700x228.png]]&lt;br /&gt;
&lt;br /&gt;
Basically what we do is take groups of questions (5 in this case), wrap them in a division and make them line up nicely horizontally and vertically. The width of the survey is also fixed to prevent wrapping issues. We do this with a JavaScript/jQuery function that inserts the necessary wrappers and then modifies styles so everything behaves properly. The top row is 5 boilerplate questions with the &amp;quot;column headers&amp;quot; as question text (the first just has a blank space). The following rows are a boilerplate with the &amp;quot;row headers&amp;quot; followed by 4 assorted questions.&lt;br /&gt;
&lt;br /&gt;
It should be noted that using conditions on these questions may result in unexpected behavior. If a question is hidden by conditions, the question(s) to the right of it will move over to take its place.&lt;br /&gt;
&lt;br /&gt;
Implementation is as follows:&lt;br /&gt;
#Create your questions keeping in mind how they will lay out when grouped into rows (in this example - boilerplate, yes/no, short text, numeric, dropdown, and repeat).&lt;br /&gt;
#In the source of the first boilerplate question add the function below (see [http://manual.limesurvey.org/wiki/Workarounds:_Manipulating_a_survey_at_runtime_using_Javascript#How_to_use_Script_.28eg._JavaScript_etc..29_in_LimeSurvey.3F How to use script]).&lt;br /&gt;
#Modify the number of rows, number of columns and the start placement in the function call (line 6) as required (the example uses 4 rows and 5 columns and the &amp;quot;array&amp;quot; starts with the third question on the page).&lt;br /&gt;
&lt;br /&gt;
The code may look intimidating at first but it&#039;s actually fairly simple. I&#039;ve laid it out as sequentially as possible and purposely used few shortcuts and many comments to make it easier to follow.&lt;br /&gt;
&lt;br /&gt;
Notes:&lt;br /&gt;
*If you use question types other than boilerplate, short text, list dropdown, numeric or yes-no, you&#039;ll need to add to the last section of code, where it hides the question text and formats the inputs for display this way.&lt;br /&gt;
*Any extra questions on the page should follow this grid of questions, not precede them.&lt;br /&gt;
&lt;br /&gt;
Javascript code:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;script type=&amp;quot;text/javascript&amp;quot; charset=&amp;quot;utf-8&amp;quot;&amp;gt;&lt;br /&gt;
	$(document).ready(function() {&lt;br /&gt;
		// Call the &amp;quot;sideBySide&amp;quot; function with number of rows, columns and start position&lt;br /&gt;
		sideBySide(4, 5, 3);&lt;br /&gt;
	});&lt;br /&gt;
&lt;br /&gt;
	function sideBySide(rows, columns, startQuestion) {&lt;br /&gt;
&lt;br /&gt;
		/*********** Display multiple questions side by side ***********/&lt;br /&gt;
&lt;br /&gt;
		if ($(&#039;div.qRow1&#039;).length == 0) {&lt;br /&gt;
			var rowNum = 0;&lt;br /&gt;
			var colNum = 1;&lt;br /&gt;
			var rowList = new Array();&lt;br /&gt;
&lt;br /&gt;
			//////// Add question classes for later use ////////&lt;br /&gt;
			&lt;br /&gt;
			// Loop through all questions and add row and column specific classes&lt;br /&gt;
			$(&#039;div[id&amp;lt;div class=&amp;quot;simplebox&amp;quot;&amp;gt;=&amp;quot;question&amp;quot;]&#039;).each(function(i) {&lt;br /&gt;
				if(i &amp;gt;= (startQuestion-1) &amp;amp;&amp;amp; rowNum &amp;lt; rows) { // This IF condition only needed if there are questions before or following the &amp;quot;inline&amp;quot; questions&lt;br /&gt;
					$(this).addClass(&#039;qRow&#039;+rowNum+&#039;&#039;).addClass(&#039;qCol&#039;+colNum+&#039;&#039;).addClass(&#039;inlineQuestion&#039;);&lt;br /&gt;
					if(rowNum == 0 &amp;amp;&amp;amp; colNum &amp;gt; 1) {&lt;br /&gt;
						$(this).addClass(&#039;columnLabel&#039;);&lt;br /&gt;
					}&lt;br /&gt;
					&lt;br /&gt;
					if(rowNum &amp;gt; 0 &amp;amp;&amp;amp; colNum == 1) {&lt;br /&gt;
						$(this).addClass(&#039;rowLabel&#039;);&lt;br /&gt;
					}&lt;br /&gt;
					else if(rowNum &amp;gt; 0 &amp;amp;&amp;amp; colNum &amp;gt; 1) {&lt;br /&gt;
						$(this).addClass(&#039;questionCell&#039;);&lt;br /&gt;
					}&lt;br /&gt;
&lt;br /&gt;
					if(colNum == columns) {&lt;br /&gt;
						rowList.push(&#039;qRow&#039;+rowNum+&#039;&#039;);&lt;br /&gt;
						rowNum++;&lt;br /&gt;
						colNum = 1;&lt;br /&gt;
					}&lt;br /&gt;
					else {&lt;br /&gt;
						colNum++;&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
				else {&lt;br /&gt;
					$(this).addClass(&#039;normalQuestion&#039;);&lt;br /&gt;
				}&lt;br /&gt;
			});&lt;br /&gt;
&lt;br /&gt;
			//////// Survey layout manipulation ////////&lt;br /&gt;
&lt;br /&gt;
			// Fix the width of the survey&lt;br /&gt;
			$(&#039;table.outerframe&#039;).css({&lt;br /&gt;
				&#039;width&#039;: &#039;900px&#039;&lt;br /&gt;
			});&lt;br /&gt;
&lt;br /&gt;
			// Wrap each &amp;quot;row&amp;quot; in a wrapper div&lt;br /&gt;
			$(rowList).each(function(i) {&lt;br /&gt;
				$(&#039;.&#039;+this+&#039;&#039;).wrapAll(&#039;&amp;lt;div id=&amp;quot;inlineWrapper&#039;+i+&#039;&amp;quot; class=&amp;quot;inlineRow&amp;quot; /&amp;gt;&#039;);&lt;br /&gt;
			});&lt;br /&gt;
&lt;br /&gt;
			// Style the wrapper divs&lt;br /&gt;
			$(&#039;.inlineRow&#039;).css({&lt;br /&gt;
				&#039;width&#039;: &#039;850px&#039;,&lt;br /&gt;
				&#039;margin&#039;: &#039;0 auto 0 auto&#039;,&lt;br /&gt;
				&#039;clear&#039;: &#039;both&#039;&lt;br /&gt;
			});&lt;br /&gt;
&lt;br /&gt;
			$( &#039;.inlineRow:first&#039; ).css({&lt;br /&gt;
				&#039;margin-top&#039;: &#039;10px&#039;&lt;br /&gt;
			});&lt;br /&gt;
&lt;br /&gt;
			// Get all the questions to sit politely side by side&lt;br /&gt;
			$( &#039;.inlineQuestion&#039; ).css({&lt;br /&gt;
				&#039;float&#039;: &#039;left&#039;,&lt;br /&gt;
				&#039;height&#039;:&#039;41px&#039;,&lt;br /&gt;
				&#039;overflow&#039;:&#039;hidden&#039;,&lt;br /&gt;
				&#039;margin-bottom&#039;: &#039;-8px&#039;&lt;br /&gt;
			});&lt;br /&gt;
			$( &#039;.inlineQuestion .questionhelp&#039; ).hide();&lt;br /&gt;
			$( &#039;.inlineQuestion .survey-question-help&#039; ).parent().hide();&lt;br /&gt;
			&lt;br /&gt;
			// A little space under the last row&lt;br /&gt;
			$( &#039;.inlineRow:last .inlineQuestion&#039; ).css({&lt;br /&gt;
				&#039;margin-bottom&#039;: &#039;10px&#039;&lt;br /&gt;
			});&lt;br /&gt;
&lt;br /&gt;
			// Any questions not displayed inline (this is only needed if there are questions following the &amp;quot;inline&amp;quot; questions)&lt;br /&gt;
			$( &#039;.normalQuestion&#039; ).css({&lt;br /&gt;
				&#039;clear&#039;: &#039;both&#039;&lt;br /&gt;
			});&lt;br /&gt;
&lt;br /&gt;
			//////// Column manipulation ////////&lt;br /&gt;
&lt;br /&gt;
			// Set the column widths - can be set individually if necessary&lt;br /&gt;
			// Must add up to less than 100%&lt;br /&gt;
			$( &#039;.qCol1&#039; ).css({&lt;br /&gt;
				&#039;width&#039;: &#039;12%&#039;&lt;br /&gt;
			});&lt;br /&gt;
&lt;br /&gt;
			$( &#039;.qCol2, .qCol3, .qCol4, .qCol5&#039; ).css({&lt;br /&gt;
				&#039;width&#039;: &#039;22%&#039;&lt;br /&gt;
			});&lt;br /&gt;
&lt;br /&gt;
			//////// Question manipulation ////////&lt;br /&gt;
&lt;br /&gt;
			// Hide the answer element in boilerplate questions&lt;br /&gt;
			$( &#039;div.boilerplate td.answer&#039; ).parent().hide();&lt;br /&gt;
&lt;br /&gt;
			// Hide the question text elements in non-boilerplate questions&lt;br /&gt;
			$(&#039;div.questionCell td.questiontext&#039;).parent().hide();&lt;br /&gt;
&lt;br /&gt;
			// Push the question tables to 100%&lt;br /&gt;
			$( &#039;div.inlineRow table&#039; ).css({&lt;br /&gt;
				&#039;width&#039;: &#039;100%&#039;&lt;br /&gt;
			});&lt;br /&gt;
&lt;br /&gt;
			// Get everything to line up nicely vertically&lt;br /&gt;
			$( &#039;.inlineQuestion td.questiontext, .inlineQuestion td.answer p&#039; ).css({&lt;br /&gt;
				&#039;text-align&#039;: &#039;center&#039;&lt;br /&gt;
			});&lt;br /&gt;
&lt;br /&gt;
			// Adjust cell heights so everything lines up nicely horizontally&lt;br /&gt;
			$( &#039;.inlineQuestion td.answer, .inlineQuestion td.questiontext&#039; ).css({&lt;br /&gt;
				&#039;height&#039;:&#039;35px&#039;,&lt;br /&gt;
				&#039;overflow&#039;:&#039;hidden&#039;,&lt;br /&gt;
				&#039;padding&#039;:&#039;0.5em&#039;&lt;br /&gt;
			});&lt;br /&gt;
			$( &#039;#inlineWrapper0 .inlineQuestion&#039; ).css({ &#039;height&#039;:&#039;50px&#039; });&lt;br /&gt;
			$( &#039;#inlineWrapper0 td.questiontext&#039; ).css({&lt;br /&gt;
				&#039;height&#039;:&#039;50px&#039;&lt;br /&gt;
			});&lt;br /&gt;
&lt;br /&gt;
			// Yes-no question styles&lt;br /&gt;
			$( &#039;div.yes-no ul&#039; ).css({&lt;br /&gt;
				&#039;text-align&#039;: &#039;center&#039;,&lt;br /&gt;
				&#039;font-size&#039;: &#039;90%&#039;,&lt;br /&gt;
				&#039;margin&#039;: &#039;0&#039;,&lt;br /&gt;
				&#039;padding-bottom&#039;: &#039;5px&#039;&lt;br /&gt;
			});&lt;br /&gt;
			$( &#039;div.yes-no li&#039; ).css({&lt;br /&gt;
				&#039;padding-right&#039;: &#039;1.5em&#039;&lt;br /&gt;
			});&lt;br /&gt;
			$( &#039;div.yes-no td.answer&#039; ).css({&lt;br /&gt;
				&#039;padding-bottom&#039;: &#039;0&#039;&lt;br /&gt;
			});&lt;br /&gt;
&lt;br /&gt;
			// Short-text question styles&lt;br /&gt;
			$( &#039;div.text-short input&#039; ).css({&lt;br /&gt;
				&#039;width&#039;: &#039;125px&#039;,&lt;br /&gt;
				&#039;margin-left&#039;: &#039;0&#039;&lt;br /&gt;
			});&lt;br /&gt;
&lt;br /&gt;
			// Numeric question styles&lt;br /&gt;
			$( &#039;div.numeric input&#039; ).css({&lt;br /&gt;
				&#039;width&#039;: &#039;125px&#039;,&lt;br /&gt;
				&#039;margin-left&#039;: &#039;0&#039;&lt;br /&gt;
			});&lt;br /&gt;
			$( &#039;div.numeric p.tip&#039; ).css({&lt;br /&gt;
				&#039;display&#039;: &#039;none&#039;&lt;br /&gt;
			});&lt;br /&gt;
&lt;br /&gt;
			// Get rid of the margins around select boxes&lt;br /&gt;
			$( &#039;p.question&#039; ).css({ &#039;margin&#039;:&#039;0&#039; });&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Star Rating System=&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Tested with: 1.85+ (7557), IE 6/7, FireFox 3.0, Safari 3.2,&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This workaround uses the [http://www.fyneworks.com/jquery/star-rating/ jQuery Star Rating Plugin] to display a series of stars that are used to generate a rating value. This value is then passed to either a hidden numeric input question or a hidden list radio question. Both methods are outlined below - use one or both depending on whether you want to use [Assessments|assessments].&lt;br /&gt;
&lt;br /&gt;
The plugin uses a series of radio inputs to generate the stars (more about these below). It allows the use of whole or partial stars as shown in [http://www.partnersinc.biz/surveys//index.php?sid=47586&amp;amp;newtest=Y&amp;amp;lang=en this demo] and the image below.&lt;br /&gt;
&lt;br /&gt;
[[File:star_rating_700x324.png]]&lt;br /&gt;
&lt;br /&gt;
==Star Rating System Using Numeric Input Question==&lt;br /&gt;
&lt;br /&gt;
Use this method if you would like your rating data to be collected as a numeric value and don&#039;t want to use [[Assessments|LimeSurvey assessments]] - it&#039;s a little easier to implement. There is a demo [http://www.partnersinc.biz/surveys//index.php?sid=47586&amp;amp;newtest=Y&amp;amp;lang=en here] (first question).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Implementation is as follows:&#039;&#039;&#039;&lt;br /&gt;
#Turn off &#039;&#039;$filterxsshtml&#039;&#039; to allow insertion of JavaScript in the questions. (See [[Optional settings#Security|documentation here]])&lt;br /&gt;
#[http://www.fyneworks.com/jquery/star-rating/ Download the plugin] and place the following included files in your template folder:&lt;br /&gt;
##jquery.MetaData.js&lt;br /&gt;
##jquery.rating.css&lt;br /&gt;
##jquery.rating.js&lt;br /&gt;
##delete.gif&lt;br /&gt;
##star.gif&lt;br /&gt;
#In the &amp;lt;head&amp;gt; section of your startpage.pstpl, add the following code to link to the files.&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;
&lt;br /&gt;
&amp;lt;script type=&amp;quot;text/javascript&amp;quot; src=&amp;quot;{TEMPLATEURL}jquery.rating.js&amp;quot; charset=&amp;quot;utf-8&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;script type=&amp;quot;text/javascript&amp;quot; src=&amp;quot;{TEMPLATEURL}jquery.MetaData.js&amp;quot; charset=&amp;quot;utf-8&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; type=&amp;quot;text/css&amp;quot; href=&amp;quot;{TEMPLATEURL}jquery.rating.css&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
5. Create a numeric input question and then in the source of the question add as many radio inputs as star segments. For example, if you would like 5 stars, each with half-segments (as in the demo Q1), you would need 10 radio inputs and that would give rating values from 1-10.&lt;br /&gt;
&lt;br /&gt;
Don&#039;t confuse these inputs with the actual question, they are just for the plugin&#039;s use.&lt;br /&gt;
&lt;br /&gt;
At this point your question source code should look something like below. Make sure that all inputs have the same name. Each input must have the same title as value and these must be sequential. Don&#039;t worry about how all of this looks in the WSYSWYG editor - the plugin is going to hide these inputs and replace them with stars.&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;
Q1 - Some question text here.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div id=&amp;quot;starContainer&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
   &amp;lt;input type=&amp;quot;radio&amp;quot; class=&amp;quot;star { split:2 }&amp;quot; title=&amp;quot;1&amp;quot; value=&amp;quot;1&amp;quot; name=&amp;quot;q1Rate&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
   &amp;lt;input type=&amp;quot;radio&amp;quot; class=&amp;quot;star { split:2 }&amp;quot; title=&amp;quot;2&amp;quot; value=&amp;quot;2&amp;quot; name=&amp;quot;q1Rate&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
   &amp;lt;input type=&amp;quot;radio&amp;quot; class=&amp;quot;star { split:2 }&amp;quot; title=&amp;quot;3&amp;quot; value=&amp;quot;3&amp;quot; name=&amp;quot;q1Rate&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
   &amp;lt;input type=&amp;quot;radio&amp;quot; class=&amp;quot;star { split:2 }&amp;quot; title=&amp;quot;4&amp;quot; value=&amp;quot;4&amp;quot; name=&amp;quot;q1Rate&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
   &amp;lt;input type=&amp;quot;radio&amp;quot; class=&amp;quot;star { split:2 }&amp;quot; title=&amp;quot;5&amp;quot; value=&amp;quot;5&amp;quot; name=&amp;quot;q1Rate&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
   &amp;lt;input type=&amp;quot;radio&amp;quot; class=&amp;quot;star { split:2 }&amp;quot; title=&amp;quot;6&amp;quot; value=&amp;quot;6&amp;quot; name=&amp;quot;q1Rate&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
   &amp;lt;input type=&amp;quot;radio&amp;quot; class=&amp;quot;star { split:2 }&amp;quot; title=&amp;quot;7&amp;quot; value=&amp;quot;7&amp;quot; name=&amp;quot;q1Rate&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
   &amp;lt;input type=&amp;quot;radio&amp;quot; class=&amp;quot;star { split:2 }&amp;quot; title=&amp;quot;8&amp;quot; value=&amp;quot;8&amp;quot; name=&amp;quot;q1Rate&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
   &amp;lt;input type=&amp;quot;radio&amp;quot; class=&amp;quot;star { split:2 }&amp;quot; title=&amp;quot;9&amp;quot; value=&amp;quot;9&amp;quot; name=&amp;quot;q1Rate&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
   &amp;lt;input type=&amp;quot;radio&amp;quot; class=&amp;quot;star { split:2 }&amp;quot; title=&amp;quot;10&amp;quot; value=&amp;quot;10&amp;quot; name=&amp;quot;q1Rate&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
6. A note on split stars. The stars in the above example are split in half by the &#039;&#039;{ split:2 }&#039;&#039; metadata. So if you don&#039;t want split stars, your inputs would look like:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;input type=&amp;quot;radio&amp;quot; class=&amp;quot;star&amp;quot; title=&amp;quot;1&amp;quot; value=&amp;quot;1&amp;quot; name=&amp;quot;q1Rate&amp;quot; /&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
And stars split into third-segments would look like:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;input type=&amp;quot;radio&amp;quot; class=&amp;quot;star { split:3 }&amp;quot; title=&amp;quot;1&amp;quot; value=&amp;quot;1&amp;quot; name=&amp;quot;q1Rate&amp;quot; /&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
7. Finally, in the source of the question add the following function after your inputs. (See [[Workarounds: Manipulating a survey at runtime using Javascript#How to use Script (eg. JavaScript etc.) in LimeSurvey?|How to use script here]])&lt;br /&gt;
&lt;br /&gt;
Some notes on the code:&lt;br /&gt;
*Replace &amp;quot;SSSSS&amp;quot;, &amp;quot;GG&amp;quot;, &amp;quot;QQ&amp;quot; in the function call at the end with the survey ID, group ID and question ID respectively.&lt;br /&gt;
*The code will hide the numeric input and pass the rating values into it as they are changed. If the rating is canceled the numeric input is nullified. If a respondent navigates away from the page then returns the code &amp;quot;remembers&amp;quot; the previous rating and displays the stars accordingly.&lt;br /&gt;
*If you want to apply it to more numeric questions on the same page simply add more calls with the appropriate IDs. (eg. handleRatingNumeric(11111, 22, 1); handleRatingNumeric(11111, 22, 2); ...) .&lt;br /&gt;
&lt;br /&gt;
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;
&amp;lt;script type=&amp;quot;text/javascript&amp;quot; charset=&amp;quot;utf-8&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
$(document).ready(function() {&lt;br /&gt;
&lt;br /&gt;
function handleRatingNumeric (sID, gID, qID) {&lt;br /&gt;
&lt;br /&gt;
   // Hide the numeric input&lt;br /&gt;
&lt;br /&gt;
   $(&#039;#question&#039; + qID + &#039; td.answer&#039;).parent().hide();&lt;br /&gt;
&lt;br /&gt;
   // Get a previous rating (if any) and use it to initialize the star display&lt;br /&gt;
&lt;br /&gt;
   var rating = $(&#039;#answer&#039; + sID + &#039;X&#039; + gID + &#039;X&#039; + qID + &#039;&#039;).val();&lt;br /&gt;
&lt;br /&gt;
   if ( rating != &#039;&#039; ) {&lt;br /&gt;
&lt;br /&gt;
       $(&#039;#question&#039; + qID + &#039; input.star&#039;).rating(&#039;select&#039;, rating);&lt;br /&gt;
&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   // Listener on the star rating cancel element&lt;br /&gt;
&lt;br /&gt;
   $(&#039;#question&#039; + qID + &#039; div.rating-cancel&#039;).click(function(event) {&lt;br /&gt;
&lt;br /&gt;
       // Nullify the rating if the Cancel element is clicked&lt;br /&gt;
&lt;br /&gt;
       rating = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
       $(&#039;#answer&#039; + sID + &#039;X&#039; + gID + &#039;X&#039; + qID + &#039;&#039;).val(rating);&lt;br /&gt;
&lt;br /&gt;
   });&lt;br /&gt;
&lt;br /&gt;
   // Listener on the star rating elements&lt;br /&gt;
&lt;br /&gt;
   $(&#039;#question&#039; + qID + &#039; div.star-rating&#039;).click(function(event) {&lt;br /&gt;
&lt;br /&gt;
       // Find the value of the highest clicked star and pass it into the text input&lt;br /&gt;
&lt;br /&gt;
       $(&#039;#question&#039; + qID + &#039; div.star-rating-on&#039;).each(function(i) {&lt;br /&gt;
&lt;br /&gt;
           rating = $(this).children(&#039;a&#039;).html( );&lt;br /&gt;
&lt;br /&gt;
       });&lt;br /&gt;
&lt;br /&gt;
       $(&#039;#answer&#039; + sID + &#039;X&#039; + gID + &#039;X&#039; + qID + &#039;&#039;).val(rating);&lt;br /&gt;
&lt;br /&gt;
   });&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Call the function for the numeric question&lt;br /&gt;
&lt;br /&gt;
handleRatingNumeric (SSSSS, GG, QQ);&lt;br /&gt;
&lt;br /&gt;
});&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;
==Star Rating System Using List (Radio) Question==&lt;br /&gt;
&lt;br /&gt;
Use this method if you would like to use [[Assessments|assessments]]. There is a demo [http://www.partnersinc.biz/surveys//index.php?sid=47586&amp;amp;newtest=Y&amp;amp;lang=en here] (second question).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Implementation is as follows:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
1. Turn off &#039;&#039;$filterxsshtml&#039;&#039; to allow insertion of JavaScript in the questions. (See [[Optional settings#Security|documentation here]])&lt;br /&gt;
&lt;br /&gt;
2. Set up the template to use custom onload functions. (See the [[Workarounds: Manipulating a survey at runtime using Javascript#Custom onload function|workaround here]])&lt;br /&gt;
&lt;br /&gt;
3. [http://www.fyneworks.com/jquery/star-rating/ Download the plugin] and place the following included files in your template folder:&lt;br /&gt;
*jquery.MetaData.js&lt;br /&gt;
*jquery.rating.css&lt;br /&gt;
*jquery.rating.js&lt;br /&gt;
*delete.gif&lt;br /&gt;
*star.gif&lt;br /&gt;
&lt;br /&gt;
4. In the &amp;lt;head&amp;gt; section of your startpage.pstpl, add the following code to link to the files.&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;
&lt;br /&gt;
&amp;lt;script type=&amp;quot;text/javascript&amp;quot; src=&amp;quot;{TEMPLATEURL}jquery.rating.js&amp;quot; charset=&amp;quot;utf-8&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;script type=&amp;quot;text/javascript&amp;quot; src=&amp;quot;{TEMPLATEURL}jquery.MetaData.js&amp;quot; charset=&amp;quot;utf-8&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; type=&amp;quot;text/css&amp;quot; href=&amp;quot;{TEMPLATEURL}jquery.rating.css&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
5. Create a list (radio) question with the same amount of sequentially numbered answers as star ratings. For example, if you want 5 whole-stars, you would create 5 answers, as in the image below, and this would give you ratings from 1-5. Note that the &amp;quot;Codes&amp;quot; and &amp;quot;Answers&amp;quot; must be sequential numbers.&lt;br /&gt;
&lt;br /&gt;
[[File:star_rating_700x156_v2.png]]&lt;br /&gt;
&lt;br /&gt;
6. In the list (radio) question, set the [[Advanced question settings|hide_tip]] question attribute to 1&lt;br /&gt;
&lt;br /&gt;
7. In the source of the question add as many radio inputs as star segments. So 5 whole-stars (as in the demo Q2), would need 5 radio inputs.&lt;br /&gt;
&lt;br /&gt;
Don&#039;t confuse these inputs with the actual question, they are just for the plugin&#039;s use.&lt;br /&gt;
&lt;br /&gt;
At this point your question source code should look something like below. Make sure that all inputs have the same name. Each input must have the same title as value and these must be sequential. Don&#039;t worry about how all of this looks in the WSYSWYG editor - the plugin is going to hide these inputs and replace them with stars.&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;
Q2 - Some question text here.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div id=&amp;quot;starContainer&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
   &amp;lt;input type=&amp;quot;radio&amp;quot; class=&amp;quot;star&amp;quot; title=&amp;quot;1&amp;quot; value=&amp;quot;1&amp;quot; name=&amp;quot;q2Rate&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
   &amp;lt;input type=&amp;quot;radio&amp;quot; class=&amp;quot;star&amp;quot; title=&amp;quot;2&amp;quot; value=&amp;quot;2&amp;quot; name=&amp;quot;q2Rate&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
   &amp;lt;input type=&amp;quot;radio&amp;quot; class=&amp;quot;star&amp;quot; title=&amp;quot;3&amp;quot; value=&amp;quot;3&amp;quot; name=&amp;quot;q2Rate&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
   &amp;lt;input type=&amp;quot;radio&amp;quot; class=&amp;quot;star&amp;quot; title=&amp;quot;4&amp;quot; value=&amp;quot;4&amp;quot; name=&amp;quot;q2Rate&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
   &amp;lt;input type=&amp;quot;radio&amp;quot; class=&amp;quot;star&amp;quot; title=&amp;quot;5&amp;quot; value=&amp;quot;5&amp;quot; name=&amp;quot;q2Rate&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
8. A note on split stars. The stars in the above example are whole-stars. If you want them split you need to add metadata to the class - something like &#039;&#039;{ split:2 }&#039;&#039;. So if you want half-stars your inputs would look like:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;input type=&amp;quot;radio&amp;quot; class=&amp;quot;star { split:2 }&amp;quot; title=&amp;quot;1&amp;quot; value=&amp;quot;1&amp;quot; name=&amp;quot;q1Rate&amp;quot; /&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
And stars split into third-segments would look like:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;input type=&amp;quot;radio&amp;quot; class=&amp;quot;star { split:3 }&amp;quot; title=&amp;quot;1&amp;quot; value=&amp;quot;1&amp;quot; name=&amp;quot;q1Rate&amp;quot; /&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
9. Finally, in the source of the question add the following function after your inputs. (See [http://docs.limesurvey.org/tiki-index.php?page=Workarounds&amp;amp;structure;=English+Instructions+for+LimeSurvey#How_to_use_Script_eg._JavaScript_etc._ How to use script here])&lt;br /&gt;
&lt;br /&gt;
Some notes on the code:&lt;br /&gt;
*Replace &amp;quot;SSSSS&amp;quot;, &amp;quot;GG&amp;quot;, &amp;quot;QQ&amp;quot; in the function call at the end with the survey ID, group ID and question ID respectively.&lt;br /&gt;
*The code will hide the question radio buttons and toggle them as the rating values are changed. If the rating is canceled all question inputs are unchecked. If a respondent navigates away from the page then returns the code &amp;quot;remembers&amp;quot; the previous rating and displays the stars accordingly.&lt;br /&gt;
*If you want to apply it to more numeric questions on the same page simply add more calls with the appropriate IDs. (eg. handleRatingRadio(11111, 22, 1); handleRatingRadio(11111, 22, 2); ...) .&lt;br /&gt;
&lt;br /&gt;
Onload 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;
&amp;lt;script type=&amp;quot;text/javascript&amp;quot; charset=&amp;quot;utf-8&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
$(document).ready(function() {&lt;br /&gt;
&lt;br /&gt;
function handleRatingRadio (sID, gID, qID) {&lt;br /&gt;
&lt;br /&gt;
   // Hide the radio input&lt;br /&gt;
&lt;br /&gt;
   $(&#039;#question&#039; + qID + &#039; td.answer&#039;).parent().hide();&lt;br /&gt;
&lt;br /&gt;
   // Get a previous rating (if any) and use it to initialize the star display&lt;br /&gt;
&lt;br /&gt;
   var rating = $(&#039;#question&#039; + qID + &#039; input.radio[checked=true]&#039;).attr(&#039;value&#039;);&lt;br /&gt;
&lt;br /&gt;
   //if ( rating != &#039;&#039; ) {&lt;br /&gt;
&lt;br /&gt;
   if ( rating ) {&lt;br /&gt;
&lt;br /&gt;
       $(&#039;#question&#039; + qID + &#039; input.star&#039;).rating(&#039;select&#039;, rating);&lt;br /&gt;
&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   // Listener on the star rating cancel element&lt;br /&gt;
&lt;br /&gt;
   $(&#039;#question&#039; + qID + &#039; div.rating-cancel&#039;).click(function(event) {&lt;br /&gt;
&lt;br /&gt;
       // Nullify the rating if the Cancel element is clicked&lt;br /&gt;
&lt;br /&gt;
       rating = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
       $(&#039;#question&#039; + qID + &#039; input.radio&#039;).attr(&#039;checked&#039;, false);&lt;br /&gt;
&lt;br /&gt;
   });&lt;br /&gt;
&lt;br /&gt;
   // Listener on the star rating elements&lt;br /&gt;
&lt;br /&gt;
   $(&#039;#question&#039; + qID + &#039; div.star-rating&#039;).click(function(event) {&lt;br /&gt;
&lt;br /&gt;
       // Find the value of the highest clicked star and pass it into the text input&lt;br /&gt;
&lt;br /&gt;
       $(&#039;#question&#039; + qID + &#039; div.star-rating-on&#039;).each(function(i) {&lt;br /&gt;
&lt;br /&gt;
           rating = $(this).children(&#039;a&#039;).html( );&lt;br /&gt;
&lt;br /&gt;
       });&lt;br /&gt;
&lt;br /&gt;
       $(&#039;#question&#039; + qID + &#039; input.radio[value=&#039; + rating + &#039;]&#039;).attr(&#039;checked&#039;, true);&lt;br /&gt;
&lt;br /&gt;
   });&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Call the function for the radio question&lt;br /&gt;
&lt;br /&gt;
handleRatingRadio (SSSSS, GG, QQ);&lt;br /&gt;
&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/script&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Variable column widths in array=&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Tested with: 1.85+ (7557), IE 6/7, Firefox 3.0, Safari 3.2&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This workaround allows you to define all column widths of an array question - as shown in the image below and [http://www.partnersinc.biz/surveys//index.php?sid=26842&amp;amp;newtest=Y&amp;amp;lang=en demonstrated here]. This example uses the default template shipped with 7557 but should be adaptable to any template.&lt;br /&gt;
&lt;br /&gt;
[[File:array_widths_701x226.gif]]&lt;br /&gt;
&lt;br /&gt;
We use a function to remove all of the widths imposed by the core code and then insert our own.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Implementation is as follows:&#039;&#039;&#039;&lt;br /&gt;
#Turn off &#039;&#039;$filterxsshtml&#039;&#039; to allow insertion of JavaScript in the questions (see [http://docs.limesurvey.org/tiki-index.php?page=Optional+settings&amp;amp;structure;=English+Instructions+for+LimeSurvey#Filtering_dangerous_HTML_tags_in_survey_objects documentation here]).&lt;br /&gt;
#Create the array question.&lt;br /&gt;
#In the source of the array question add the following script (see [[Workarounds: Manipulating a survey at runtime using Javascript#How to use Script (eg. JavaScript etc.) in LimeSurvey?|How to use script here]]).&lt;br /&gt;
#Replace all instances of QQ with the question ID.&lt;br /&gt;
#In the third section of code, adjust the widths and add/remove columns as necessary. This example is for an array with a question text column followed by 3 answer columns as shown above.&lt;br /&gt;
#In the final section adjust the question text alignment to your liking&lt;br /&gt;
&lt;br /&gt;
Onload 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;
&amp;lt;script type=&amp;quot;text/javascript&amp;quot; charset=&amp;quot;utf-8&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
$(document).ready(function() {&lt;br /&gt;
&lt;br /&gt;
   // Get rid of all the widths that the API imposes&lt;br /&gt;
&lt;br /&gt;
   $( &#039;div#questionQQ table.question col&#039; ).attr(&#039;width&#039;, &#039;&#039;);&lt;br /&gt;
&lt;br /&gt;
   $( &#039;div#questionQQ table.question thead td&#039; ).attr(&#039;width&#039;, &#039;&#039;);&lt;br /&gt;
&lt;br /&gt;
   // Define a width for the question table so we can do so for its children&lt;br /&gt;
&lt;br /&gt;
   // NOTE: Keep this to 95% or less so IE will behave&lt;br /&gt;
&lt;br /&gt;
   $( &#039;div#questionQQ table.question&#039; ).attr(&#039;width&#039;, &#039;95%&#039;);&lt;br /&gt;
&lt;br /&gt;
   // Define the column widths&lt;br /&gt;
&lt;br /&gt;
   // Add or remove columns and adjust widths as necessary but widths should add up to 100%&lt;br /&gt;
&lt;br /&gt;
   // NOTE: Columns must be sequentially numbered starting at 0 - eg, td:eq(0), td:eq(1), td:eq(2).....&lt;br /&gt;
&lt;br /&gt;
   $( &#039;div#questionQQ table.question tbody th:eq(0)&#039; ).css({ &#039;width&#039;:&#039;10%&#039; }); // Answer text column&lt;br /&gt;
&lt;br /&gt;
   $( &#039;div#questionQQ table.question tbody td:eq(0)&#039; ).css({ &#039;width&#039;:&#039;50%&#039; }); // First answer column&lt;br /&gt;
&lt;br /&gt;
   $( &#039;div#questionQQ table.question tbody td:eq(1)&#039; ).css({ &#039;width&#039;:&#039;20%&#039; }); // Second answer column&lt;br /&gt;
&lt;br /&gt;
   $( &#039;div#questionQQ table.question tbody td:eq(2)&#039; ).css({ &#039;width&#039;:&#039;20%&#039; }); // Third answer column&lt;br /&gt;
&lt;br /&gt;
   // Push the text input widths to 95% of their parent containers&lt;br /&gt;
&lt;br /&gt;
   $( &#039;div#questionQQ table.question input[type=&amp;quot;text&amp;quot;]&#039; ).css({ &#039;width&#039;:&#039;95%&#039; });&lt;br /&gt;
&lt;br /&gt;
   // Align the answer text - feel free to experiment&lt;br /&gt;
&lt;br /&gt;
   $( &#039;div#questionQQ table.question tbody th&#039; ).css({&#039;text-align&#039;:&#039;center&#039;});&lt;br /&gt;
&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/script&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Use images for radio buttons and checkboxes=&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Tested with: LimeSurvey 1.92/2.0, using IE 9, FireFox 13, Chrome 16, Safari 5&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This workaround uses an adaptation of the jQuery imagetick.js plugin to replace the default radio buttons and checkboxes with images as pictured below:&lt;br /&gt;
&lt;br /&gt;
[[File:images.png]]&lt;br /&gt;
&lt;br /&gt;
This adaptation will work in the following question types:&lt;br /&gt;
*Array&lt;br /&gt;
*Array by column&lt;br /&gt;
*Array dual scale&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 (Yes-No-Uncertain)&lt;br /&gt;
*Gender&lt;br /&gt;
*Yes-No&lt;br /&gt;
*Multiple choice&lt;br /&gt;
*Multiple choice with comments&lt;br /&gt;
*5 point choice&lt;br /&gt;
*List (Radio)&lt;br /&gt;
*List with comment&lt;br /&gt;
&lt;br /&gt;
==LimeSurvey 1.92 and earlier implementation==&lt;br /&gt;
#[[Workarounds: Manipulating a survey at runtime using Javascript#How to use Script (eg. JavaScript etc.) in LimeSurvey?|Set up your survey to use JavaScript]].&lt;br /&gt;
#Download [[Media:imagetick_lime_v1.3.zip|this modified version of the plugin]].&lt;br /&gt;
#Extract all files and place them in your template directory.&lt;br /&gt;
#Add the following line to the &amp;lt;head&amp;gt; element in your startpage.pstpl &#039;&#039;&#039;BEFORE&#039;&#039;&#039; the call for template.js:&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&amp;lt;script type=&amp;quot;text/javascript&amp;quot; src=&amp;quot;{TEMPLATEURL}imagetick_lime.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
#Add the following to the source of a question or the group description&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&amp;lt;script type=&amp;quot;text/javascript&amp;quot; charset=&amp;quot;utf-8&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
   $(document).ready(function(){&lt;br /&gt;
&lt;br /&gt;
       var templatePath = $(&#039;head link[href*=&amp;quot;template.css&amp;quot;]&#039;).attr(&#039;href&#039;).replace(/template.css/, &#039;&#039;);&lt;br /&gt;
&lt;br /&gt;
       // Apply images to radios&lt;br /&gt;
&lt;br /&gt;
       $(&#039;input[type=&amp;quot;radio&amp;quot;]&#039;).imageTick({&lt;br /&gt;
&lt;br /&gt;
           // Image to use as a selected state of the radio&lt;br /&gt;
&lt;br /&gt;
           tick_image_path:  templatePath+&amp;quot;radio.gif&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
           // Image to use as a non-selected state&lt;br /&gt;
&lt;br /&gt;
           no_tick_image_path:  templatePath+&amp;quot;no_radio.gif&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
           // Class to apply to all radio images that are dynamically created&lt;br /&gt;
&lt;br /&gt;
           image_tick_class: &amp;quot;radios&amp;quot;&lt;br /&gt;
&lt;br /&gt;
       });&lt;br /&gt;
&lt;br /&gt;
       // Apply images to checkboxes&lt;br /&gt;
&lt;br /&gt;
       $(&#039;input[type=&amp;quot;checkbox&amp;quot;]&#039;).imageTick({&lt;br /&gt;
&lt;br /&gt;
           // Image to use as a selected state of the checkbox&lt;br /&gt;
&lt;br /&gt;
           tick_image_path: templatePath+&amp;quot;check.gif&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
           // Image to use as a non-selected state&lt;br /&gt;
&lt;br /&gt;
           no_tick_image_path: templatePath+&amp;quot;no_check.gif&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
           // Class to apply to all checkbox images that are dynamically created&lt;br /&gt;
&lt;br /&gt;
           image_tick_class: &amp;quot;checkboxes&amp;quot;&lt;br /&gt;
&lt;br /&gt;
       });&lt;br /&gt;
&lt;br /&gt;
   });&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/script&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can also call the imagetick function from template.js. Skip the last step above and add the following to the end of template.js. Replace &amp;quot;yourTemplateName&amp;quot; with your template directory name.&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;$(document).ready(function(){&lt;br /&gt;
&lt;br /&gt;
   var templatePath = $(&#039;head link[href*=&amp;quot;template.css&amp;quot;]&#039;).attr(&#039;href&#039;).replace(/template.css/, &#039;&#039;);&lt;br /&gt;
&lt;br /&gt;
   // Apply images to radios&lt;br /&gt;
&lt;br /&gt;
   $(&#039;input[type=&amp;quot;radio&amp;quot;]&#039;).imageTick({&lt;br /&gt;
&lt;br /&gt;
       // Image to use as a selected state of the radio&lt;br /&gt;
&lt;br /&gt;
       tick_image_path: templatePath+&amp;quot;radio.gif&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
       // Image to use as a non-selected state&lt;br /&gt;
&lt;br /&gt;
       no_tick_image_path: templatePath+&amp;quot;no_radio.gif&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
       // Class to apply to all radio images that are dynamically created&lt;br /&gt;
&lt;br /&gt;
       image_tick_class: &amp;quot;radios&amp;quot;&lt;br /&gt;
&lt;br /&gt;
   });&lt;br /&gt;
&lt;br /&gt;
   // Apply images to checkboxes&lt;br /&gt;
&lt;br /&gt;
   $(&#039;input[type=&amp;quot;checkbox&amp;quot;]&#039;).imageTick({&lt;br /&gt;
&lt;br /&gt;
       // Image to use as a selected state of the checkbox&lt;br /&gt;
&lt;br /&gt;
       tick_image_path: templatePath+&amp;quot;check.gif&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
       // Image to use as a non-selected state&lt;br /&gt;
&lt;br /&gt;
       no_tick_image_path: templatePath+&amp;quot;no_check.gif&amp;quot;,&lt;br /&gt;
&lt;br /&gt;
       // Class to apply to all checkbox images that are dynamically created&lt;br /&gt;
&lt;br /&gt;
       image_tick_class: &amp;quot;checkboxes&amp;quot;&lt;br /&gt;
&lt;br /&gt;
   });&lt;br /&gt;
&lt;br /&gt;
});    &amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you want to apply it to only one question on a page use selector (where QQ is the question ID)&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;$(&#039;#questionQQ input[type=&amp;quot;radio&amp;quot;]&#039;)&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you want to apply it to a single radio button in a question (to maybe have different images for each option) use selector (where SSSSS is the survey ID, GG is the group ID, QQ is the question ID, AA is the answer code)&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;$(&amp;quot;input#answerSSSSSXGGXQQAA&amp;quot;)&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==LimeSurvey 2.0 and later implementation==&lt;br /&gt;
&lt;br /&gt;
Follow the instructions above with these changes:&lt;br /&gt;
#Download [[Media:imagetick_lime_v2.zip|this modified version of the plugin for 2.0 and up]] instead of the one mentioned above and add all contained files to your template directory.&lt;br /&gt;
#Add these lines to the &amp;lt;head&amp;gt; element in your startpage.pstpl instead of the one above:&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&amp;lt;script type=&amp;quot;text/javascript&amp;quot; src=&amp;quot;{TEMPLATEURL}imagetick_lime_2.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; type=&amp;quot;text/css&amp;quot; href=&amp;quot;{TEMPLATEURL}imagetick_lime_2.css&amp;quot; /&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Thanks to Jordan Boesch for the original plugin.&lt;br /&gt;
&lt;br /&gt;
=Changing the position an layout of an individual question using &amp;quot;question code&amp;quot;=&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Tested with: 1.87+ (6536)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
To use this very flexible workaround you first have to apply a minor change to the question.pstpl of the used template.&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;
&amp;lt;div class=&amp;quot;survey-question&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
   &amp;lt;div class=&amp;quot;survey-question-text&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
needs to be changed to&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;
&amp;lt;div class=&amp;quot;survey-question&amp;quot; id=&amp;quot;{QUESTION_CODE}&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
   &amp;lt;div class=&amp;quot;survey-question-text&amp;quot; id=&amp;quot;{QUESTION_CODE}&amp;quot; &amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
this change won&#039;t change anything in the layout and can be left in the template even if you don&#039;t need this workaround. It&#039;s just a means to have a handle to actually change individual questions.&lt;br /&gt;
&lt;br /&gt;
You can then use a code such as the following in the question text to make question specific format changes. &amp;quot;SAMPLE&amp;quot; needs to be replaced with the concerning question code and javascript has to be allowed ([[Workarounds: Manipulating a survey at runtime using Javascript#How to use Script (eg. JavaScript etc.) in LimeSurvey?|older versions of limesurvey]], under global settings for newer versions).&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;
&amp;lt;script type=&amp;quot;text/javascript&amp;quot; charset=&amp;quot;utf-8&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
document.getElementById(&#039;SAMPLE&#039;).style.borderTop= &amp;quot;0px&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
document.getElementById(&#039;SAMPLE&#039;).style.marginTop= &amp;quot;-62px&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
document.getElementById(&#039;SAMPLE&#039;).style.marginLeft= &amp;quot;30px&amp;quot;;&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;
This sample code will hide the border at the top of the question, will move the whole question up by 62px and to the right by 30px. Using this workaround you can change a whole a lot of things concerning format and positions of a specific question without changing all the questions. A (German) list of all the allowed options can be found [http://de.selfhtml.org/javascript/objekte/style.htm#style_eigenschaften here].&lt;br /&gt;
&lt;br /&gt;
=Create MaxDiff question type=&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Tested with: 1.87+ (8518), IE 6/7/8, Firefox 3.6, Safari 3.2&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This workaround uses JavaScript to convert an &#039;&#039;&#039;&#039;&#039;Array (flexible labels) by column&#039;&#039;&#039;&#039;&#039; question into a [http://en.wikipedia.org/wiki/MaxDiff MaxDiff] question type.&lt;br /&gt;
&lt;br /&gt;
[[File:max_diff_596x253.gif]]&lt;br /&gt;
&lt;br /&gt;
There is a demo [http://www.partnersinc.biz/surveys//index.php?sid=29191&amp;amp;newtest=Y&amp;amp;lang=en here] and implementation is as follows.&lt;br /&gt;
#[[Workarounds: Manipulating a survey at runtime using Javascript#How to use Script (eg. JavaScript etc.) in LimeSurvey?|Set up your survey to use JavaScript]].&lt;br /&gt;
#Create an &#039;&#039;&#039;&#039;&#039;Array (flexible labels) by column&#039;&#039;&#039;&#039;&#039; question with 2 &amp;quot;answers&amp;quot; - these will be the left and right columns.&lt;br /&gt;
#Assign a label set to the question - these will be the labels in the center column.&lt;br /&gt;
#Place the following script in the source of the question or in the group description.&lt;br /&gt;
#In  line 5, replace &amp;quot;QQ&amp;quot; with the ID of the question and modify the message to your needs.&lt;br /&gt;
#Adjust the styles in lines 15-18 as required.&lt;br /&gt;
&lt;br /&gt;
The script moves the question columns into the MaxDiff configuration and alerts the user if they select the same option for both max and min columns.&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;
&amp;lt;script type=&amp;quot;text/javascript&amp;quot; charset=&amp;quot;utf-8&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
   $(document).ready(function(){&lt;br /&gt;
&lt;br /&gt;
       maxDiff(QQ, &#039;You cannot select this answer twice.&#039;);&lt;br /&gt;
&lt;br /&gt;
       function maxDiff(qID, msg) {&lt;br /&gt;
&lt;br /&gt;
           // Move the cells around&lt;br /&gt;
&lt;br /&gt;
           $(&#039;#question&#039;+qID+&#039; table.question col:eq(1)&#039;).prependTo(&#039;colgroup.col-responses&#039;);&lt;br /&gt;
&lt;br /&gt;
           $(&#039;#question&#039;+qID+&#039; table.question thead tr:eq(0) th:eq(0)&#039;).prependTo(&#039;#question&#039;+qID+&#039; table.question thead tr:eq(0)&#039;);&lt;br /&gt;
&lt;br /&gt;
           $(&#039;#question&#039;+qID+&#039; table.question tbody tr&#039;).each(function(i){&lt;br /&gt;
&lt;br /&gt;
               $(&#039;td:eq(0)&#039;, this).prependTo(this);&lt;br /&gt;
&lt;br /&gt;
           });&lt;br /&gt;
&lt;br /&gt;
           // Style stuff&lt;br /&gt;
&lt;br /&gt;
           $(&#039;#question&#039;+qID+&#039; table.question col.odd&#039;).css({ &#039;background-color&#039;:&#039;transparent&#039; });&lt;br /&gt;
&lt;br /&gt;
           $(&#039;#question&#039;+qID+&#039; table.question tbody th&#039;).css({ &#039;text-align&#039;:&#039;center&#039; });&lt;br /&gt;
&lt;br /&gt;
           $(&#039;#question&#039;+qID+&#039; table.question tbody tr:even td, #question&#039;+qID+&#039; table.question tbody tr:even th&#039;).css({ &#039;background-color&#039;:&#039;#F1F1F1&#039; });&lt;br /&gt;
&lt;br /&gt;
           $(&#039;#question&#039;+qID+&#039; table.question tbody tr:odd td, #question&#039;+qID+&#039; table.question tbody tr:odd th&#039;).css({ &#039;background-color&#039;:&#039;#FCFCFC&#039; });&lt;br /&gt;
&lt;br /&gt;
           // Prevent clicking twice in the same row&lt;br /&gt;
&lt;br /&gt;
           $(&#039;#question&#039;+qID+&#039; input.radio&#039;).mousedown(function () {&lt;br /&gt;
&lt;br /&gt;
               var clickRow = $(this).parents(&#039;tr:eq(0)&#039;);&lt;br /&gt;
&lt;br /&gt;
               if ($(&#039;input.radio:checked&#039;, clickRow).length &amp;gt; 0) {&lt;br /&gt;
&lt;br /&gt;
                   alert (msg);&lt;br /&gt;
&lt;br /&gt;
                   return false;&lt;br /&gt;
&lt;br /&gt;
               }&lt;br /&gt;
&lt;br /&gt;
           });&lt;br /&gt;
&lt;br /&gt;
           $(&#039;#question&#039;+qID+&#039; table.question tbody td&#039;).mousedown(function () {&lt;br /&gt;
&lt;br /&gt;
               var clickRow = $(this).parents(&#039;tr:eq(0)&#039;);&lt;br /&gt;
&lt;br /&gt;
               if ($(&#039;input.radio:checked&#039;, clickRow).length &amp;gt; 0) {&lt;br /&gt;
&lt;br /&gt;
                   alert (msg);&lt;br /&gt;
&lt;br /&gt;
                   return false;&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;
&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;
=Load SVG Code From Drawing Tool=&lt;br /&gt;
&lt;br /&gt;
This workaround uses JavaScript/jQuery to load a drawing tool and store the results in a huge-text question. The details are outlined in the [[Workarounds: Manipulating a survey at runtime using Javascript#Load SVG Code From Drawing Tool|JavaScript section of the workarounds]].&lt;br /&gt;
&lt;br /&gt;
=Minimum or Maximum Date in Datepicker=&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Tested with: 1.90, IE 7/8, Firefox 3.6, Safari 3.2&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
You can set the minimum or maximum selectible date in a datepicker as follows&lt;br /&gt;
&lt;br /&gt;
[[Workarounds: Manipulating a survey at runtime using Javascript#How to use Script (eg. JavaScript etc.) in LimeSurvey?|Set up your survey to use JavaScript]] and add the following to the source of the date question text or help. Replace &amp;quot;QQ&amp;quot; with the date question ID.&lt;br /&gt;
&lt;br /&gt;
For a minimum date of April 15, 2010:&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&amp;lt;script type=&amp;quot;text/javascript&amp;quot; charset=&amp;quot;utf-8&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
   $(document).ready(function() {&lt;br /&gt;
&lt;br /&gt;
       var qID = QQ;&lt;br /&gt;
&lt;br /&gt;
       $(&#039;#question&#039;+qID+&#039; .popupdate&#039;).datepicker( &#039;option&#039;, &#039;minDate&#039;, new Date(2010, 4-1, 15) );&lt;br /&gt;
&lt;br /&gt;
   });&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;
For a minimum date of the current date (today):&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&amp;lt;script type=&amp;quot;text/javascript&amp;quot; charset=&amp;quot;utf-8&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
   $(document).ready(function() {&lt;br /&gt;
&lt;br /&gt;
       var qID = QQ;&lt;br /&gt;
&lt;br /&gt;
       $(&#039;#question&#039;+qID+&#039; .popupdate&#039;).datepicker( &#039;option&#039;, &#039;minDate&#039;, new Date() );&lt;br /&gt;
&lt;br /&gt;
   });&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;
For a maximum date of May 10, 2015:&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&amp;lt;script type=&amp;quot;text/javascript&amp;quot; charset=&amp;quot;utf-8&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
   $(document).ready(function() {&lt;br /&gt;
&lt;br /&gt;
       var qID = QQ;&lt;br /&gt;
&lt;br /&gt;
       $(&#039;#question&#039;+qID+&#039; .popupdate&#039;).datepicker( &#039;option&#039;, &#039;maxDate&#039;, new Date(2015, 5-1, 10) );&lt;br /&gt;
&lt;br /&gt;
   });&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;
More details here - http://jqueryui.com/demos/datepicker/#option-minDate&lt;br /&gt;
&lt;br /&gt;
=Evaluative Space Grid (ESG)=&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Tested with: 1.91, IE 7/8, Firefox 3.6, Safari 3.2&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The evaluative space grid (ESG) is a two-dimensional grid that provides a single-item measure of positivity and negativity (Larsen et al, 2009). See [http://leeds-faculty.colorado.edu/mcgrawp/pdf/larsen.norris.mcgraw.hawkley.cacioppo.2009.pdf page 4 of this PDF].&lt;br /&gt;
&lt;br /&gt;
This can be accomplished using a multiple-numeric question, some simple HTML and a little JavaScript.&lt;br /&gt;
&lt;br /&gt;
A table can be shown in the question. When a respondent clicks a grid cell in the table JavaScript loads the coordinates of the cell into the multiple-numeric question inputs.&lt;br /&gt;
&lt;br /&gt;
[[File:space_grid.png]]&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
#Create a Multiple Numeric question with two sub-questions labelled &amp;quot;X&amp;quot; and &amp;quot;Y&amp;quot;.&lt;br /&gt;
#Add the following HTML to the source of the question to create the table:&amp;lt;syntaxhighlight lang=&amp;quot;html4strict&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;table class=&amp;quot;spaceGrid&amp;quot;&amp;gt;&lt;br /&gt;
	&amp;lt;tr&amp;gt;&lt;br /&gt;
		&amp;lt;td rowspan=&amp;quot;5&amp;quot; class=&amp;quot;yAxisLabel&amp;quot;&amp;gt;How NEGATIVE&amp;lt;br&amp;gt;&lt;br /&gt;
			do you feel about&amp;lt;br&amp;gt;&lt;br /&gt;
		the stimulus?&amp;lt;/td&amp;gt;&lt;br /&gt;
		&amp;lt;td class=&amp;quot;yLabel&amp;quot;&amp;gt;Extremely&amp;lt;/td&amp;gt;&lt;br /&gt;
		&amp;lt;td class=&amp;quot;gridCell&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
		&amp;lt;td class=&amp;quot;gridCell&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
		&amp;lt;td class=&amp;quot;gridCell&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
		&amp;lt;td class=&amp;quot;gridCell&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
		&amp;lt;td class=&amp;quot;gridCell&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
	&amp;lt;/tr&amp;gt;&lt;br /&gt;
	&amp;lt;tr&amp;gt;&lt;br /&gt;
		&amp;lt;td class=&amp;quot;yLabel&amp;quot;&amp;gt;Quite a bit&amp;lt;/td&amp;gt;&lt;br /&gt;
		&amp;lt;td class=&amp;quot;gridCell&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
		&amp;lt;td class=&amp;quot;gridCell&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
		&amp;lt;td class=&amp;quot;gridCell&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
		&amp;lt;td class=&amp;quot;gridCell&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
		&amp;lt;td class=&amp;quot;gridCell&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
	&amp;lt;/tr&amp;gt;&lt;br /&gt;
	&amp;lt;tr&amp;gt;&lt;br /&gt;
		&amp;lt;td class=&amp;quot;yLabel&amp;quot;&amp;gt;Moderately&amp;lt;/td&amp;gt;&lt;br /&gt;
		&amp;lt;td class=&amp;quot;gridCell&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
		&amp;lt;td class=&amp;quot;gridCell&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
		&amp;lt;td class=&amp;quot;gridCell&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
		&amp;lt;td class=&amp;quot;gridCell&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
		&amp;lt;td class=&amp;quot;gridCell&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
	&amp;lt;/tr&amp;gt;&lt;br /&gt;
	&amp;lt;tr&amp;gt;&lt;br /&gt;
		&amp;lt;td class=&amp;quot;yLabel&amp;quot;&amp;gt;Slightly&amp;lt;/td&amp;gt;&lt;br /&gt;
		&amp;lt;td class=&amp;quot;gridCell&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
		&amp;lt;td class=&amp;quot;gridCell&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
		&amp;lt;td class=&amp;quot;gridCell&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
		&amp;lt;td class=&amp;quot;gridCell&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
		&amp;lt;td class=&amp;quot;gridCell&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
	&amp;lt;/tr&amp;gt;&lt;br /&gt;
	&amp;lt;tr&amp;gt;&lt;br /&gt;
		&amp;lt;td class=&amp;quot;yLabel&amp;quot;&amp;gt;Not at all&amp;lt;/td&amp;gt;&lt;br /&gt;
		&amp;lt;td class=&amp;quot;gridCell&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
		&amp;lt;td class=&amp;quot;gridCell&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
		&amp;lt;td class=&amp;quot;gridCell&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
		&amp;lt;td class=&amp;quot;gridCell&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
		&amp;lt;td class=&amp;quot;gridCell&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
	&amp;lt;/tr&amp;gt;&lt;br /&gt;
	&amp;lt;tr&amp;gt;&lt;br /&gt;
		&amp;lt;td class=&amp;quot;blankCell&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
		&amp;lt;td class=&amp;quot;blankCell&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
		&amp;lt;td class=&amp;quot;xLabel&amp;quot;&amp;gt;Not at all&amp;lt;/td&amp;gt;&lt;br /&gt;
		&amp;lt;td class=&amp;quot;xLabel&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;yLabel&amp;quot;&amp;gt;Slightly&amp;lt;/span&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
		&amp;lt;td class=&amp;quot;xLabel&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;yLabel&amp;quot;&amp;gt;Moderately&amp;lt;/span&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
		&amp;lt;td class=&amp;quot;xLabel&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;yLabel&amp;quot;&amp;gt;Quite a bit&amp;lt;/span&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
		&amp;lt;td class=&amp;quot;xLabel&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;yLabel&amp;quot;&amp;gt;Extremely&amp;lt;/span&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
	&amp;lt;/tr&amp;gt;&lt;br /&gt;
	&amp;lt;tr&amp;gt;&lt;br /&gt;
		&amp;lt;td class=&amp;quot;blankCell&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
		&amp;lt;td class=&amp;quot;blankCell&amp;quot;&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
		&amp;lt;td colspan=&amp;quot;5&amp;quot; class=&amp;quot;xAxisLabel&amp;quot;&amp;gt;How POSITIVE do you feel about the stimulus?&amp;lt;/td&amp;gt;&lt;br /&gt;
	&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
#Add the following styles to the end of your template.css file:&amp;lt;syntaxhighlight lang=&amp;quot;css&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
.spaceGrid {&lt;br /&gt;
	border: 0 none;&lt;br /&gt;
	border-collapse: collapse;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.spaceGrid td {&lt;br /&gt;
	padding: 0 3px;&lt;br /&gt;
	text-align: center !important;&lt;br /&gt;
	border: 0 none;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
td.xAxisLabel {&lt;br /&gt;
	padding-top: 10px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
td.yAxisLabel {&lt;br /&gt;
	padding-right: 10px;&lt;br /&gt;
	width: 125px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
td.xLabel {&lt;br /&gt;
	height: 20px;&lt;br /&gt;
	font-weight: normal;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
td.yLabel {&lt;br /&gt;
	text-align: right !important;&lt;br /&gt;
	font-weight: normal;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
td.gridCell {&lt;br /&gt;
	width: 70px;&lt;br /&gt;
	height: 70px;&lt;br /&gt;
	border: 1px solid #666666;&lt;br /&gt;
	background-color: #FFFFFF;&lt;br /&gt;
	cursor: pointer;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
td.checkedCell {&lt;br /&gt;
	background-color: #66FF00;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
#Add the following to the end of your template.js file:&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;	&lt;br /&gt;
$(document).ready(function() {&lt;br /&gt;
&lt;br /&gt;
	// Listener on the grid cells&lt;br /&gt;
	$(&#039;.gridCell&#039;).click(function(){&lt;br /&gt;
&lt;br /&gt;
		// Define some vars&lt;br /&gt;
		var parentQ = $(this).parents(&#039;div[id&amp;lt;/div&amp;gt;=&amp;quot;question&amp;quot;]:eq(0)&#039;);&lt;br /&gt;
		var parentTable = $(this).parents(&#039;table.spaceGrid:eq(0)&#039;);&lt;br /&gt;
		var parentRow = $(this).parent();&lt;br /&gt;
		var numGridCell = $(&#039;.gridCell&#039;).length;&lt;br /&gt;
		var numCols = $(&#039;.gridCell&#039;, parentRow).length;&lt;br /&gt;
		var numRows = numGridCell/numCols;&lt;br /&gt;
&lt;br /&gt;
		// Add class to checked cell&lt;br /&gt;
		$(&#039;.checkedCell&#039;, parentQ).removeClass(&#039;checkedCell&#039;);&lt;br /&gt;
		$(this).addClass(&#039;checkedCell&#039;);&lt;br /&gt;
&lt;br /&gt;
		// Find the cell coordinates&lt;br /&gt;
		var reverseRowIndex = (numRows - $(&#039;tr&#039;, parentTable).index($(parentRow)));&lt;br /&gt;
		var colIndex = $(&#039;.gridCell&#039;, parentRow).index($(this)) + 1;&lt;br /&gt;
&lt;br /&gt;
		// Load coordinates into inputs&lt;br /&gt;
		$(&#039;input.text:eq(0)&#039;, parentQ).val(colIndex);&lt;br /&gt;
		$(&#039;input.text:eq(1)&#039;, parentQ).val(reverseRowIndex);&lt;br /&gt;
	});&lt;br /&gt;
&lt;br /&gt;
});&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
The script should automatically handle different grid sizes.&lt;br /&gt;
&lt;br /&gt;
=Slider Highlighting=&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Tested with: 1.91, IE 7/8, Firefox 3.6, Safari 3.2&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
You may want to highlight a slider after it has been moved/changed to allow respondents to easily see which slider sub-questions have been answered.&lt;br /&gt;
&lt;br /&gt;
[[File:Capture.PNG]]&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
#Add the following to the end of &#039;&#039;&#039;template.js&#039;&#039;&#039;:&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
$(&#039;html&#039;).bind(&#039;slidecreate&#039;, function(event, ui) {&lt;br /&gt;
	$(&#039;.slider_callout&#039;).each(function(i){&lt;br /&gt;
		if($(this).text().length &amp;gt; 0) {&lt;br /&gt;
			$(this).parents(&#039;li:eq(0)&#039;).addClass(&#039;changedSlider&#039;);&lt;br /&gt;
		}&lt;br /&gt;
	});&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
$(document).ready(function() {&lt;br /&gt;
	$(&#039;.ui-slider-horizontal&#039;).bind(&#039;slidechange&#039;, function(event, ui) {&lt;br /&gt;
	 $(this).parents(&#039;li:eq(0)&#039;).addClass(&#039;changedSlider&#039;);&lt;br /&gt;
	});&lt;br /&gt;
});&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
#Add something like the following to the end of &#039;&#039;&#039;template.css&#039;&#039;&#039; (these styles are for the default template and would need to be modified for other templates):&amp;lt;syntaxhighlight lang=&amp;quot;css&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
.numeric-multi .answer li {&lt;br /&gt;
	border-bottom: 5px solid #FFFFFF;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.numeric-multi .answer li label {&lt;br /&gt;
	background-color: #FFFFFF;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.numeric-multi .answer li div.multinum-slider {&lt;br /&gt;
	margin: 1.5em 0.5em 0.2em 0;&lt;br /&gt;
	padding-left: 0.5em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.ui-slider-1 {&lt;br /&gt;
	margin-bottom: 10px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.changedSlider {&lt;br /&gt;
	background-color: #99FFFF;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Sliders in Array-Numbers or Array-Dual-Scale-Numbers=&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Tested with: 1.91, IE 7/8/9, Firefox 3/7, Safari 5, Chrome 15&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This workaround will replace the dropdowns in &#039;&#039;&#039;&#039;&#039;array-numbers&#039;&#039;&#039;&#039;&#039; or &#039;&#039;&#039;&#039;&#039;array-dual-scale-numbers&#039;&#039;&#039;&#039;&#039; questions with sliders. The sliders will automatically have the same minimum, maximum and steps that you set in the advanced question settings.&lt;br /&gt;
&lt;br /&gt;
[[File:custom_sliders_1.png]]&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
There is a [http://www.partnersinc.biz/surveys//index.php?sid=66653&amp;amp;newtest=Y&amp;amp;lang=en &#039;&#039;&#039;demo here&#039;&#039;&#039;].&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
#[[Workarounds: Manipulating a survey at runtime using Javascript#How to use Script (eg. JavaScript etc.) in LimeSurvey?|Set up your survey to use JavaScript]].&lt;br /&gt;
#Create your array-numbers or array-dual-scale-numbers question.&lt;br /&gt;
#Add the following to the source of the question. Replace &amp;quot;QQ&amp;quot; with the array question ID. (NOTE: In 1.92 or newer, you can replace &amp;quot;QQ&amp;quot; with &amp;quot;{QID}&amp;quot;)&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;script type=&amp;quot;text/javascript&amp;quot; charset=&amp;quot;utf-8&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
   $(document).ready(function() {&lt;br /&gt;
&lt;br /&gt;
		insertSlider (QQ);&lt;br /&gt;
&lt;br /&gt;
		function insertSlider (qID) {&lt;br /&gt;
&lt;br /&gt;
			$(&#039;#question&#039;+qID+&#039; select&#039;).each(function(i, el){&lt;br /&gt;
&lt;br /&gt;
				// Hide the dropdown&lt;br /&gt;
				$(el).hide();&lt;br /&gt;
&lt;br /&gt;
				var id = $(el).attr(&#039;id&#039;).replace(/#/g,&#039;-&#039;);&lt;br /&gt;
&lt;br /&gt;
				// Some dropdown values&lt;br /&gt;
				var currentVal = Number($(&#039;option:selected&#039;, el).val());&lt;br /&gt;
				var firstVal = Number($(&#039;option[value!=&amp;quot;&amp;quot;]:first&#039;, el).val());&lt;br /&gt;
				var secondVal = Number($(&#039;option[value!=&amp;quot;&amp;quot;]:first&#039;, el).next(&#039;option&#039;).val());&lt;br /&gt;
				var lastVal = Number($(&#039;option[value!=&amp;quot;&amp;quot;]:last&#039;, el).val());&lt;br /&gt;
&lt;br /&gt;
				// Insert a container for the slider&lt;br /&gt;
				var container = $(&#039;&amp;lt;div class=&amp;quot;customSliderWrapper&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;).insertAfter(el);&lt;br /&gt;
&lt;br /&gt;
				// Insert a callout&lt;br /&gt;
				var callout = $(&#039;&amp;lt;div id=&amp;quot;callOut-&#039;+id+&#039;&amp;quot; class=&amp;quot;customCallout&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;).appendTo(container).text($(&#039;option:selected&#039;, el).val());&lt;br /&gt;
&lt;br /&gt;
				// Initiate the slider&lt;br /&gt;
				var slider = $(&#039;&amp;lt;div id=&amp;quot;slider-&#039;+id+&#039;&amp;quot; class=&amp;quot;customSlider&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;).appendTo(container).slider({&lt;br /&gt;
					min: firstVal,&lt;br /&gt;
					max: lastVal,&lt;br /&gt;
					range: &#039;min&#039;,&lt;br /&gt;
					value: currentVal,&lt;br /&gt;
					step: secondVal - firstVal,&lt;br /&gt;
					slide: function( event, ui ) {&lt;br /&gt;
						$(&#039;option[value=&amp;quot;&#039;+ui.value+&#039;&amp;quot;]&#039;, el).attr(&#039;selected&#039;, &#039;selected&#039;);&lt;br /&gt;
						function updateCustomCallout() {&lt;br /&gt;
							$(&#039;#callOut-&#039;+id).text($(&#039;option:selected&#039;, el).val()).css({ &#039;left&#039;: $(&#039;#slider-&#039;+id+&#039; .ui-slider-handle&#039;).css(&#039;left&#039;) });&lt;br /&gt;
						}&lt;br /&gt;
						// Delay updating the callout because it was picking up the last postion of the slider&lt;br /&gt;
						setTimeout(updateCustomCallout, 10);&lt;br /&gt;
					}&lt;br /&gt;
				});&lt;br /&gt;
&lt;br /&gt;
				// Change the slider if the dropdown is changed&lt;br /&gt;
				// (not required if dropdown is hidden)&lt;br /&gt;
				$(el).change(function() {&lt;br /&gt;
					slider.slider(&#039;value&#039;, Number($(&#039;option:selected&#039;, el).val()));&lt;br /&gt;
					$(&#039;#callOut-&#039;+id).text($(&#039;option:selected&#039;, el).val());&lt;br /&gt;
				});&lt;br /&gt;
&lt;br /&gt;
				// Set a value as soon as the slider handle is clicked&lt;br /&gt;
				$(&#039;#slider-&#039;+id+&#039; .ui-slider-handle&#039;).mousedown(function() {&lt;br /&gt;
					$(&#039;option[value=&amp;quot;&#039;+slider.slider(&#039;value&#039;)+&#039;&amp;quot;]&#039;, el).attr(&#039;selected&#039;, &#039;selected&#039;);&lt;br /&gt;
					$(&#039;#callOut-&#039;+id).text(slider.slider(&#039;value&#039;));&lt;br /&gt;
				});&lt;br /&gt;
			});&lt;br /&gt;
		}&lt;br /&gt;
	});&lt;br /&gt;
&amp;lt;/script&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
#Add something like the following to the end of &#039;&#039;&#039;template.css&#039;&#039;&#039; (these styles are for the default template and may need to be modified for other templates):&amp;lt;syntaxhighlight lang=&amp;quot;css&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
table.innerframe {&lt;br /&gt;
	width:850px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.array-multi-flexi table.question {&lt;br /&gt;
	width:90%;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.customCallout {&lt;br /&gt;
	position: absolute;&lt;br /&gt;
	top: 0;&lt;br /&gt;
	left: 0;&lt;br /&gt;
	width: 50px;&lt;br /&gt;
	height: 1.75em;&lt;br /&gt;
	text-align: left;&lt;br /&gt;
	font-weight: bold;&lt;br /&gt;
	margin: 0 0 0 -0.3em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.customSliderWrapper {&lt;br /&gt;
	position: relative;&lt;br /&gt;
	margin: 0 10px;&lt;br /&gt;
	padding-top: 1.75em;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Vertical Sliders=&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Tested with: 1.92+, 2.00+, IE 9, Firefox 13, Chrome 19&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This workaround uses a custom jQuery plugin to apply vertical sliders to multiple-numeric questions. You can download a sample template here (with the plugin in template.js) - [[Media:default_vertical_sliders.zip|vertical slider template]] - and a sample survey here - [[Media:demo_vertical_sliders.lss|vertical slider survey]].&lt;br /&gt;
&lt;br /&gt;
[[File:verticalsliders_1.jpg]]&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
# Create your multi-numeric question(s). Do NOT use any of the slider advanced settings.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
#Add the following to the end of template.js. Replace &amp;quot;QQ&amp;quot; (line 5) with the question ID and adjust the options in the function call as desired. Repeat the call as many times as you need for more questions&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;$(document).ready(function(){&lt;br /&gt;
&lt;br /&gt;
	// Call the vertical slider plugin with the question ID&lt;br /&gt;
	// Edit options here as desired&lt;br /&gt;
	$(&#039;#questionQQ&#039;).lsVerticalSlider({&lt;br /&gt;
		minValue		:0,		// Minimum value (default 0)&lt;br /&gt;
		maxValue		:200,	// Maximum value (default 100)&lt;br /&gt;
		startValue		:100,	// Start value (default null)&lt;br /&gt;
		step			:10,	// Slider increments (default 1)&lt;br /&gt;
		height			:100,	// Height of slider in pixels (default 200)&lt;br /&gt;
		recordStart		:true,	// Record the start value? (default no)&lt;br /&gt;
		showMin			:true,	// Show minimum value? (default no)&lt;br /&gt;
		showMax			:true	// Show maximum value? (default no)&lt;br /&gt;
	});&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
// NO EDITING REQUIRED BELOW HERE&lt;br /&gt;
// A jQuery plugin to convert multiple-numeric questions to vertical sliders&lt;br /&gt;
(function( $ ){&lt;br /&gt;
	$.fn.lsVerticalSlider = function(options) {&lt;br /&gt;
&lt;br /&gt;
		// The defaults, extended and modified with any passed in the function call&lt;br /&gt;
		var opts = $.extend( {&lt;br /&gt;
			minValue		:0,&lt;br /&gt;
			maxValue		:100,&lt;br /&gt;
			startValue		:&#039;&#039;,&lt;br /&gt;
			step			:1,&lt;br /&gt;
			height			:150,&lt;br /&gt;
			recordStart		:false,&lt;br /&gt;
			showMin			:false,&lt;br /&gt;
			showMax			:false&lt;br /&gt;
		}, options);&lt;br /&gt;
&lt;br /&gt;
		return this.each(function() {&lt;br /&gt;
&lt;br /&gt;
			var $this = $(this);&lt;br /&gt;
&lt;br /&gt;
			// Some classes for the question and sub-questions&lt;br /&gt;
			$this.addClass(&#039;vertical-slider-question&#039;);&lt;br /&gt;
			$(&#039;li:[id&amp;lt;div class=&amp;quot;simplebox&amp;quot;&amp;gt;=&amp;quot;javatbd&amp;quot;]&#039;, $this).addClass(&#039;vertical-slider-sub-question&#039;);&lt;br /&gt;
&lt;br /&gt;
			// Loop through the sub-questions&lt;br /&gt;
			$(&#039;li:[id&amp;lt;/div&amp;gt;=&amp;quot;javatbd&amp;quot;]&#039;, $this).each(function(i){&lt;br /&gt;
				var itemID = $(this).attr(&#039;id&#039;).replace(/javatbd/, &#039;&#039;);&lt;br /&gt;
&lt;br /&gt;
				// Check for pre-existing answer&lt;br /&gt;
				if($(&#039;#answer&#039;+itemID).val() != &#039;&#039;) {&lt;br /&gt;
					opts.startValue = $(&#039;#answer&#039;+itemID).val();&lt;br /&gt;
				}&lt;br /&gt;
&lt;br /&gt;
				// Insert the slider elements&lt;br /&gt;
				$(&#039;#answer&#039;+itemID).after(&lt;br /&gt;
					&#039;&amp;lt;div class=&amp;quot;vertical-slider-max-min&amp;quot; style=&amp;quot;height:&#039;+(opts.height+2)+&#039;px;&amp;quot;&amp;gt; \&lt;br /&gt;
						&amp;lt;div class=&amp;quot;vertical-slider-max&amp;quot;&amp;gt;&amp;lt;/div&amp;gt; \&lt;br /&gt;
						&amp;lt;div class=&amp;quot;vertical-slider-min&amp;quot;&amp;gt;&amp;lt;/div&amp;gt; \&lt;br /&gt;
					&amp;lt;/div&amp;gt; \&lt;br /&gt;
					&amp;lt;div id=&amp;quot;vertical-slider-&#039;+itemID+&#039;&amp;quot; class=&amp;quot;vertical-slider&amp;quot; style=&amp;quot;height:&#039;+opts.height+&#039;px;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt; \&lt;br /&gt;
					&amp;lt;div class=&amp;quot;vertical-slider-callout-wrapper&amp;quot; style=&amp;quot;height:&#039;+(opts.height+2)+&#039;px;&amp;quot;&amp;gt; \&lt;br /&gt;
						&amp;lt;div class=&amp;quot;vertical-slider-callout&amp;quot; id=&amp;quot;slider-callout-&#039;+itemID+&#039;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt; \&lt;br /&gt;
					&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
				);&lt;br /&gt;
&lt;br /&gt;
				// Show min/max if option is set&lt;br /&gt;
				if(opts.showMax) {&lt;br /&gt;
					$(&#039;.vertical-slider-max&#039;, $this).text(opts.maxValue);&lt;br /&gt;
				}&lt;br /&gt;
&lt;br /&gt;
				if(opts.showMin) {&lt;br /&gt;
					$(&#039;.vertical-slider-min&#039;, $this).text(opts.minValue);&lt;br /&gt;
				}&lt;br /&gt;
&lt;br /&gt;
				// Initiate the slider&lt;br /&gt;
				$(&#039;#vertical-slider-&#039;+itemID).slider({&lt;br /&gt;
					orientation: &#039;vertical&#039;,&lt;br /&gt;
					range: &#039;min&#039;,&lt;br /&gt;
					min: opts.minValue,&lt;br /&gt;
					max: opts.maxValue,&lt;br /&gt;
					value: opts.startValue,&lt;br /&gt;
					step: opts.step,&lt;br /&gt;
					slide: function(event, ui) {&lt;br /&gt;
						$(&#039;#answer&#039;+itemID).val(ui.value);&lt;br /&gt;
						$(&#039;#slider-callout-&#039;+itemID).text(ui.value);&lt;br /&gt;
						setTimeout(function() {&lt;br /&gt;
							$(&#039;#slider-callout-&#039;+itemID).css({ &#039;bottom&#039;:$(&#039;#vertical-slider-&#039;+itemID+&#039; .ui-slider-handle&#039;).css(&#039;bottom&#039;) }).show();&lt;br /&gt;
						}, 10);&lt;br /&gt;
					},&lt;br /&gt;
					create: function(event, ui) {&lt;br /&gt;
						// Initial values and positions&lt;br /&gt;
						if($(&#039;#answer&#039;+itemID).val() != &#039;&#039;) { // Pre-existing answer&lt;br /&gt;
							$(&#039;#slider-callout-&#039;+itemID).text(opts.startValue);&lt;br /&gt;
						}&lt;br /&gt;
						else if(opts.recordStart) { // Record the start value (if option is set)&lt;br /&gt;
							$(&#039;#answer&#039;+itemID).val(opts.startValue);&lt;br /&gt;
							$(&#039;#slider-callout-&#039;+itemID).text(opts.startValue);&lt;br /&gt;
						}&lt;br /&gt;
						else {&lt;br /&gt;
							$(&#039;#slider-callout-&#039;+itemID).hide();&lt;br /&gt;
						}&lt;br /&gt;
						$(&#039;#slider-callout-&#039;+itemID).css({ &#039;bottom&#039;:$(&#039;#vertical-slider-&#039;+itemID+&#039; .ui-slider-handle&#039;).css(&#039;bottom&#039;) });&lt;br /&gt;
					}&lt;br /&gt;
				});&lt;br /&gt;
			});&lt;br /&gt;
		});&lt;br /&gt;
	};&lt;br /&gt;
})( jQuery );&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
#Add the following to the end of template.css (these styles are for the default template):&amp;lt;syntaxhighlight lang=&amp;quot;css&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;/* Vertical slider styles and overrides */&lt;br /&gt;
.vertical-slider-question p.tip {&lt;br /&gt;
	display: none;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.vertical-slider-sub-question {&lt;br /&gt;
	float: left;&lt;br /&gt;
	margin: 0 3em 0 0 !important;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.vertical-slider-question label {&lt;br /&gt;
	display: block;&lt;br /&gt;
	padding: 0 0 0.75em 0 !important;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.vertical-slider-question span.input {&lt;br /&gt;
	padding: 0.3em 0 0 0;&lt;br /&gt;
	display: block;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.vertical-slider-question input.text {&lt;br /&gt;
	display: none;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.vertical-slider {&lt;br /&gt;
	float: left;&lt;br /&gt;
	border-radius: 4px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.vertical-slider-question .ui-slider-handle {&lt;br /&gt;
	top: auto;&lt;br /&gt;
	border-radius: 4px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.vertical-slider-max-min,&lt;br /&gt;
.vertical-slider-callout-wrapper {&lt;br /&gt;
	float: left;&lt;br /&gt;
	position: relative;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.vertical-slider-callout-wrapper {&lt;br /&gt;
	min-width: 3em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.vertical-slider-max-min {&lt;br /&gt;
	margin-right: 0.5em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.vertical-slider-max,&lt;br /&gt;
.vertical-slider-min {&lt;br /&gt;
	font-size: 0.8em;&lt;br /&gt;
	color:#666666;&lt;br /&gt;
	line-height: 1;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.vertical-slider-max {&lt;br /&gt;
	margin-top: -0.5em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.vertical-slider-min {&lt;br /&gt;
	position: absolute;&lt;br /&gt;
	right: 0;&lt;br /&gt;
	bottom: 0;&lt;br /&gt;
	margin-bottom: -0.5em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.vertical-slider-callout {&lt;br /&gt;
	position: absolute;&lt;br /&gt;
	top: auto;&lt;br /&gt;
	margin: 0 0 -0.6em 0.5em;&lt;br /&gt;
	padding: 0.1em;&lt;br /&gt;
	font-size: 0.9em;&lt;br /&gt;
	color:#000000;&lt;br /&gt;
	line-height: 1;&lt;br /&gt;
	background: #F8F8FF;&lt;br /&gt;
	border: 1px solid #D2E0F2;&lt;br /&gt;
	border-radius: 4px;&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Range Slider=&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Tested with: 1.92+, 2.00+, IE 9, Firefox 13, Chrome 19&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This workaround uses a custom jQuery plugin to insert a jQuery UI range slider into a multi-numeric question and automatically populate that question&#039;s inputs with the range min and max values. You can download a sample template here - [[Media:Demo_Range_Slider.zip|range slider template]] - and a sample survey here - [[Media:Limesurvey_survey_range_slider.lss|range slider survey]].&lt;br /&gt;
&lt;br /&gt;
[[File:Range_slider.jpg]]&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
The plugin handles:&lt;br /&gt;
*previous answers&lt;br /&gt;
*slider max/min&lt;br /&gt;
*range min start&lt;br /&gt;
*range max start&lt;br /&gt;
*range span min&lt;br /&gt;
*slider step&lt;br /&gt;
*slider width&lt;br /&gt;
*record the start values&lt;br /&gt;
*show slider max and min&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Requirements:&lt;br /&gt;
*LimeSurvey 1.92 or newer&lt;br /&gt;
*A multiple-numeric question with two sub-questions&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
# Create your multi-numeric question. Do NOT use any of the slider advanced settings.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
#Add the following to the end of template.js.&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;// A jQuery plugin to display a range slider in LimeSurvey&lt;br /&gt;
(function( $ ){&lt;br /&gt;
 &lt;br /&gt;
	$.fn.lsRangeSlider = function(options) {  &lt;br /&gt;
 &lt;br /&gt;
		// The defaults, extended and modified with any passed in the function call&lt;br /&gt;
		var opts = $.extend( {&lt;br /&gt;
			range			:true, &lt;br /&gt;
			sliderMin		:0, &lt;br /&gt;
			sliderMax		:100,&lt;br /&gt;
			rangeStartMin		:&#039;&#039;,&lt;br /&gt;
			rangeStartMax		:&#039;&#039;,&lt;br /&gt;
			minRangeSpan		:0,&lt;br /&gt;
			step			:1,&lt;br /&gt;
			width			:250, &lt;br /&gt;
			recordStart		:false,&lt;br /&gt;
			showMin			:false,&lt;br /&gt;
			showMax			:false&lt;br /&gt;
		}, options);&lt;br /&gt;
 &lt;br /&gt;
		return this.each(function() { &lt;br /&gt;
 &lt;br /&gt;
			if($(this).hasClass(&#039;numeric-multi&#039;) &amp;amp;&amp;amp; $(&#039;input.text&#039;, this).length == 2) {&lt;br /&gt;
 &lt;br /&gt;
				// Define some vars	&lt;br /&gt;
				var $this = $(this);&lt;br /&gt;
				var qID = $(this).attr(&#039;id&#039;).split(&#039;question&#039;)[1];&lt;br /&gt;
				var rangeMinInput = $(&#039;input.text:eq(0)&#039;, $this); &lt;br /&gt;
				var rangeMaxInput = $(&#039;input.text:eq(1)&#039;, $this); &lt;br /&gt;
 &lt;br /&gt;
				// Some classes for the question and sub-questions&lt;br /&gt;
				$this.addClass(&#039;range-slider-question&#039;);&lt;br /&gt;
 &lt;br /&gt;
				// Check for pre-existing answer&lt;br /&gt;
				if($(rangeMinInput).val() != &#039;&#039; &amp;amp;&amp;amp; $(rangeMinInput).val() != &#039;&#039;) {&lt;br /&gt;
					opts.rangeStartMin = $(rangeMinInput).val();&lt;br /&gt;
					opts.rangeStartMax = $(rangeMaxInput).val();&lt;br /&gt;
				}&lt;br /&gt;
 &lt;br /&gt;
				// Insert the slider elements&lt;br /&gt;
				$(&#039;.subquestions-list&#039;, $this).before(&lt;br /&gt;
					&#039;&amp;lt;div class=&amp;quot;range-slider-wrapper&amp;quot;&amp;gt; \&lt;br /&gt;
						&amp;lt;div class=&amp;quot;range-slider-min&amp;quot;&amp;gt;&amp;lt;/div&amp;gt; \&lt;br /&gt;
						&amp;lt;div id=&amp;quot;range-slider-&#039;+qID+&#039;&amp;quot; class=&amp;quot;range-slider&amp;quot; style=&amp;quot;width:&#039;+opts.width+&#039;px;&amp;quot;&amp;gt; \&lt;br /&gt;
							&amp;lt;div class=&amp;quot;range-slider-callout&amp;quot; id=&amp;quot;slider-callout-min-&#039;+qID+&#039;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt; \&lt;br /&gt;
							&amp;lt;div class=&amp;quot;range-slider-callout&amp;quot; id=&amp;quot;slider-callout-max-&#039;+qID+&#039;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt; \&lt;br /&gt;
						&amp;lt;/div&amp;gt; \&lt;br /&gt;
						&amp;lt;div class=&amp;quot;range-slider-max&amp;quot;&amp;gt;&amp;lt;/div&amp;gt; \&lt;br /&gt;
						&amp;lt;div style=&amp;quot;clear:both;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt; \&lt;br /&gt;
					&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
				);&lt;br /&gt;
 &lt;br /&gt;
				// Show min/max if option is set&lt;br /&gt;
				if(opts.showMax) {&lt;br /&gt;
					$(&#039;.range-slider-max&#039;, $this).text(opts.sliderMax);&lt;br /&gt;
				}&lt;br /&gt;
				if(opts.showMin) {&lt;br /&gt;
					$(&#039;.range-slider-min&#039;, $this).text(opts.sliderMin);&lt;br /&gt;
				}&lt;br /&gt;
 &lt;br /&gt;
				// Initiate the slider&lt;br /&gt;
				var rangeMin;&lt;br /&gt;
				var rangeMax;&lt;br /&gt;
				if(opts.rangeStartMin == &#039;&#039; || opts.rangeStartMin &amp;lt; opts.sliderMin || opts.rangeStartMin &amp;gt; opts.rangeStartMax) {&lt;br /&gt;
					rangeMin = opts.sliderMin+((opts.sliderMax-opts.sliderMin)*0.3333);&lt;br /&gt;
				}&lt;br /&gt;
				else {&lt;br /&gt;
					rangeMin = opts.rangeStartMin;&lt;br /&gt;
				}&lt;br /&gt;
				if(opts.rangeStartMax == &#039;&#039; || opts.rangeStartMax &amp;gt; opts.sliderMax || opts.rangeStartMax &amp;lt; opts.rangeStartMin) {&lt;br /&gt;
					rangeMax = opts.sliderMin+((opts.sliderMax-opts.sliderMin)*0.6667);&lt;br /&gt;
				}&lt;br /&gt;
				else {&lt;br /&gt;
					rangeMax = opts.rangeStartMax;&lt;br /&gt;
				}&lt;br /&gt;
				$(&#039;#range-slider-&#039;+qID).slider({&lt;br /&gt;
					range: true,&lt;br /&gt;
					min: opts.sliderMin,&lt;br /&gt;
					max: opts.sliderMax, &lt;br /&gt;
					values: [ rangeMin, rangeMax ],&lt;br /&gt;
					step: opts.step,&lt;br /&gt;
					slide: function(event, ui) {&lt;br /&gt;
						if((ui.values[1] - ui.values[0]) &amp;lt; opts.minRangeSpan) {&lt;br /&gt;
							return false; // Nothing happens if less than minRangeSpan&lt;br /&gt;
						}&lt;br /&gt;
						$(rangeMinInput).val(ui.values[0]);&lt;br /&gt;
						$(rangeMaxInput).val(ui.values[1]);&lt;br /&gt;
						$(&#039;#slider-callout-min-&#039;+qID).text(ui.values[0]);&lt;br /&gt;
						$(&#039;#slider-callout-max-&#039;+qID).text(ui.values[1]);&lt;br /&gt;
						setTimeout(function() { &lt;br /&gt;
							$(&#039;#slider-callout-min-&#039;+qID).css({ &#039;left&#039;:$(&#039;.ui-slider-handle:eq(0)&#039;, $this).position().left - $(&#039;#slider-callout-min-&#039;+qID).outerWidth() - ($(&#039;.ui-slider-handle:eq(1)&#039;, $this).outerWidth()/2)+&#039;px&#039; }).show();&lt;br /&gt;
							$(&#039;#slider-callout-max-&#039;+qID).css({ &#039;left&#039;:($(&#039;.ui-slider-handle:eq(1)&#039;, $this).position().left)+($(&#039;.ui-slider-handle:eq(1)&#039;, $this).outerWidth()/2)+&#039;px&#039; }).show();&lt;br /&gt;
						}, 10);&lt;br /&gt;
					},&lt;br /&gt;
					create: function(event, ui) {&lt;br /&gt;
						// Initial values and positions&lt;br /&gt;
						if($(rangeMinInput).val() != &#039;&#039; &amp;amp;&amp;amp; $(rangeMaxInput).val() != &#039;&#039;) { // Pre-existing answer&lt;br /&gt;
							$(&#039;#slider-callout-min-&#039;+qID).text(opts.rangeStartMin);&lt;br /&gt;
							$(&#039;#slider-callout-max-&#039;+qID).text(opts.rangeStartMax);&lt;br /&gt;
						}&lt;br /&gt;
						else if(opts.recordStart &amp;amp;&amp;amp; opts.rangeStartMin &amp;amp;&amp;amp; opts.rangeStartMin &amp;amp;&amp;amp; $(rangeMinInput).val() == &#039;&#039; &amp;amp;&amp;amp; $(rangeMaxInput).val() == &#039;&#039;) { // Record the start value (if option is set)&lt;br /&gt;
							$(rangeMinInput).val(opts.rangeStartMin);&lt;br /&gt;
							$(rangeMaxInput).val(opts.rangeStartMax);&lt;br /&gt;
							$(&#039;#slider-callout-min-&#039;+qID).text(opts.rangeStartMin);&lt;br /&gt;
							$(&#039;#slider-callout-max-&#039;+qID).text(opts.rangeStartMax);&lt;br /&gt;
						}&lt;br /&gt;
						else {&lt;br /&gt;
							$(&#039;.range-slider-callout&#039;, $this).hide();&lt;br /&gt;
						} &lt;br /&gt;
						$(&#039;#slider-callout-min-&#039;+qID).css({ &#039;left&#039;:$(&#039;.ui-slider-handle:eq(0)&#039;, $this).position().left - $(&#039;#slider-callout-min-&#039;+qID).outerWidth() - ($(&#039;.ui-slider-handle:eq(1)&#039;, $this).outerWidth()/2)+&#039;px&#039; });&lt;br /&gt;
						$(&#039;#slider-callout-max-&#039;+qID).css({ &#039;left&#039;:($(&#039;.ui-slider-handle:eq(1)&#039;, $this).position().left)+($(&#039;.ui-slider-handle:eq(1)&#039;, $this).outerWidth()/2)+&#039;px&#039; });&lt;br /&gt;
					}&lt;br /&gt;
				});&lt;br /&gt;
			}&lt;br /&gt;
		});&lt;br /&gt;
 &lt;br /&gt;
	};&lt;br /&gt;
})( jQuery );&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
#Add the following to the end of template.css (these styles are for the default template but easily modified for others):&amp;lt;syntaxhighlight lang=&amp;quot;css&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
.range-slider-question p.tip,&lt;br /&gt;
.range-slider-question .subquestions-list {&lt;br /&gt;
	display: none;&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
.range-slider-wrapper {&lt;br /&gt;
	clear: both;&lt;br /&gt;
	margin: 10px 0;&lt;br /&gt;
	padding-top: 20px;&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
.range-slider,&lt;br /&gt;
.range-slider-max,&lt;br /&gt;
.range-slider-min {&lt;br /&gt;
	float: left;&lt;br /&gt;
	position: relative;&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
.range-slider-max,&lt;br /&gt;
.range-slider-min {&lt;br /&gt;
	font-size: 0.8em;&lt;br /&gt;
	color:#666666;&lt;br /&gt;
	line-height: 1.20;&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
.range-slider-min {&lt;br /&gt;
	margin-right: 5px;&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
.range-slider-max {&lt;br /&gt;
	margin-left: 5px;&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
.range-slider-question .ui-slider-handle {&lt;br /&gt;
	top: -4px;&lt;br /&gt;
	border-radius: 4px;&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
.range-slider-callout {&lt;br /&gt;
	position: absolute;&lt;br /&gt;
	top: -30px;&lt;br /&gt;
	margin: 0;&lt;br /&gt;
	min-width: 1.3em;&lt;br /&gt;
	padding: 0.1em;&lt;br /&gt;
	font-size: 0.9em;&lt;br /&gt;
	color:#000000;&lt;br /&gt;
	line-height: 1;&lt;br /&gt;
	text-align: center;&lt;br /&gt;
	background: #F8F8FF;&lt;br /&gt;
	border: 1px solid #D2E0F2;&lt;br /&gt;
	border-radius: 4px;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
#Then, add something like this to the source of your question to apply the plugin with some custom option settings (I think the comments explain the options adequately)&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;script type=&amp;quot;text/javascript&amp;quot; charset=&amp;quot;utf-8&amp;quot;&amp;gt;&lt;br /&gt;
	$(document).ready(function(){&lt;br /&gt;
 &lt;br /&gt;
		$(&#039;#question{QID}&#039;).lsRangeSlider({&lt;br /&gt;
			sliderMin	:0,	// Minimum slider value (default 0)&lt;br /&gt;
			sliderMax	:100,	// Maximum slider value (default 100) &lt;br /&gt;
			rangeStartMin	:20,	// Minimum range handle start value  &lt;br /&gt;
			rangeStartMax	:80,	// Maximum range handle start value  &lt;br /&gt;
			minRangeSpan	:5,	// Minimum allowed range span &lt;br /&gt;
			step		:1,	// Slider increments (default 1)&lt;br /&gt;
			width		:400,	// Width of slider in pixels (default 250)&lt;br /&gt;
			recordStart	:true,	// Record the start value? (default no)&lt;br /&gt;
			showMin		:true,	// Show slider minimum value? (default no)&lt;br /&gt;
			showMax		:true	// Show slider maximum value? (default no)&lt;br /&gt;
		});&lt;br /&gt;
 &lt;br /&gt;
	});&lt;br /&gt;
&amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
#Or, to apply the plugin with the default option settings&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;script type=&amp;quot;text/javascript&amp;quot; charset=&amp;quot;utf-8&amp;quot;&amp;gt;&lt;br /&gt;
	$(document).ready(function(){&lt;br /&gt;
 &lt;br /&gt;
		$(&#039;#question{QID}&#039;).lsRangeSlider();&lt;br /&gt;
 &lt;br /&gt;
	});&lt;br /&gt;
&amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Split your sample into legs (cells) that see slightly different wording and media=&lt;br /&gt;
&lt;br /&gt;
Sometimes you may need to test candidate A vs candidate B or brand 1 vs brand 2 &amp;amp;hellip; vs brand n. Typically in such cases the phrasing of the questionnaire is identical except for the brand (candidate) and some logo/media. Rather than create several questionnaires it is best to control survey logic by assigning respondents to different groups and showing them different versions of the questionnaire.&lt;br /&gt;
&lt;br /&gt;
The logical engine in the current version (1.91) does not support this but you can still do it using the attribute fields in the token table. The instructions below are not really a workaround, but more of a translation of conditional logic to database questionnaire logic.&lt;br /&gt;
&lt;br /&gt;
This works for closed surveys. If your survey is not closed you may want to consider ways to create automatically tokens for each respondent like: &amp;quot;Create token on the fly and Edit completed survey&amp;quot;: http://bugs.limesurvey.org/view.php?id=2982&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Case A: you need different text for each version&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Step 1: you create a tokens table adding attribute fields for each variation you need: [[Tokens#User-defined attribute fields|User defined attribute fields]]. For example you may store in attribute_1 the name of the candidate, in attribute_2 the name of the party etc.&lt;br /&gt;
&lt;br /&gt;
Step 2 You export the structure of your tokens database and populate it with the relevant values for the attribute fields. Then import it back&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
http://img502.imageshack.us/img502/7425/58d0ff2c68d74366a81e6f7.png&lt;br /&gt;
&lt;br /&gt;
Please use the instructions here: [[Tokens#Importing/exporting tokens|importing and exporting tokens]], and pay attention because this can be error-prone.&lt;br /&gt;
&lt;br /&gt;
Step 3&lt;br /&gt;
&lt;br /&gt;
When creating a question use the insert replacement field icon http://img502.imageshack.us/img502/540/81a6c17d49f04f88bd52e72.png to insert your proper keyword.&lt;br /&gt;
&lt;br /&gt;
This is it. The overall process is quite simple once you get the hang of using tokens, but the database can be space-consuming if you are running on limited resources.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Case B: you need to run different media, from public hosting websites.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The process is just like in case A, just that you will populate the attribute field with unique identifiers for the media.&lt;br /&gt;
&lt;br /&gt;
See below an example on how to embed a youtube video&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&amp;lt;iframe allowfullscreen=&amp;quot;&amp;quot; frameborder=&amp;quot;0&amp;quot; height=&amp;quot;349&amp;quot; src=&amp;quot;http://www.youtube.com/embed/&#039;&#039;&#039;{TOKEN:ATTRIBUTE_5}&#039;&#039;&#039;?rel=0&amp;amp;amp;modestbranding=1&amp;amp;amp;loop=0&amp;amp;amp;controls=0&amp;amp;amp;autoplay=1&amp;amp;amp;rel=0&amp;amp;amp;showinfo=0&amp;amp;amp;showsearch=0&amp;amp;amp;iv_load_policy=o&amp;quot; width=&amp;quot;560&amp;quot;&amp;gt;&amp;lt;/iframe&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you embed images you will want to make sure that the hotlinks for your pictures only differ by the image ID. IF not, you may use a larger portion, or maybe even the entire URL as your unique identifier. As said before, please consider how much space you are allowed for your databases.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Case C: you want to run media from your server, which is organized in relevant folders&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
For this scenario I will assume your media is organized as follows&lt;br /&gt;
&lt;br /&gt;
Project folder ...leg folder (for each leg) ... media (1 to n). You can use a FTP client to upload this structure to you LS installation.&lt;br /&gt;
&lt;br /&gt;
In this case you only need to store the &amp;lt;leg folder&amp;gt; into the tokens table and then use this info to build your embed tag. This may free a significant amount of space,&lt;br /&gt;
&lt;br /&gt;
For example if you have the data as below...&lt;br /&gt;
&lt;br /&gt;
http://img534.imageshack.us/img534/8967/a62e6ff48476492c8795f79.png&lt;br /&gt;
&lt;br /&gt;
&amp;amp;hellip; then your embed for the party logo will look somewhere along these lines:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&amp;lt;img src=&amp;quot;[path to project folder]/&#039;&#039;&#039;{TOKEN:ATTRIBUTE_3}&#039;&#039;&#039;/logo1.png&amp;quot; alt=&amp;quot;&#039;&#039;&#039;{TOKEN:ATTRIBUTE_2}&#039;&#039;&#039;&amp;quot;&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The alt tag is, of course, optional.&lt;br /&gt;
***&lt;br /&gt;
&lt;br /&gt;
You  can match and mix all 3 cases as it suites you best. You need to be a little careful when you work with tokens and embed tags, but it will save you from using intricate and error-prone survey logic or from duplicating surveys endlessly.&lt;br /&gt;
&lt;br /&gt;
=Limit the language options dropdown on the list surveys page=&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;simplebox&amp;quot;&amp;gt;Note: This feature is implemented in Version 2.0&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This solution allows you to define (in config.php) a comma-delimited list of languages you want in the dropdown.  It is not optimized (it loads all the languages and then unsets everything you don&#039;t want), but is fairly easy to implement.&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;
$supportedLanguagesKeys = &#039;en,vi&#039;;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Filter out everything except the your selected languages (if defined).&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;
   // if $supportedLanguagesKeys is defined in config, filter&lt;br /&gt;
&lt;br /&gt;
   if (!empty($GLOBALS[&#039;supportedLanguagesKeys&#039;]))&lt;br /&gt;
&lt;br /&gt;
   foreach (array_keys($supportedLanguages) as $lang) {&lt;br /&gt;
&lt;br /&gt;
     if (!in_array($lang, explode(&#039;,&#039;, $GLOBALS[&#039;supportedLanguagesKeys&#039;]))) {&lt;br /&gt;
&lt;br /&gt;
       unset($supportedLanguages[$lang]);&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;
Now only my languages, plus the base language, is displayed. To get rid of the redundant base language, do the following&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;
   } elseif (!isset($surveyid))&lt;br /&gt;
&lt;br /&gt;
   {&lt;br /&gt;
&lt;br /&gt;
       global $defaultlang, $baselang;&lt;br /&gt;
&lt;br /&gt;
       $htmlcode = &amp;quot;&amp;lt;select name=\&amp;quot;select\&amp;quot; class=&#039;languagechanger&#039; onchange=\&amp;quot;javascript:window.location=this.value\&amp;quot;&amp;gt;\n&amp;quot;;&lt;br /&gt;
#    REMOVE THE NEXT LINE OR COMMENT IT OUT)&lt;br /&gt;
&lt;br /&gt;
       $htmlcode .= &amp;quot;&amp;lt;option value=\&amp;quot;$relativeurl/index.php?lang=&amp;quot;. $defaultlang .&amp;quot;$tokenparam\&amp;quot;&amp;gt;&amp;quot;.getLanguageNameFromCode($defaultlang,false).&amp;quot;&amp;lt;/option&amp;gt;\n&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
   foreach(getlanguagedata() as $key=&amp;gt;$val)&lt;br /&gt;
&lt;br /&gt;
       {&lt;br /&gt;
&lt;br /&gt;
           $htmlcode .= &amp;quot;\t&amp;lt;option value=\&amp;quot;$relativeurl/index.php?lang=&amp;quot;.$key.&amp;quot;$tokenparam\&amp;quot; &amp;quot;;&lt;br /&gt;
&lt;br /&gt;
           if ($key == $baselang) $htmlcode .= &amp;quot; selected=&#039;selected&#039;&amp;quot;; /* ADD THIS TO SET SELECTION */&lt;br /&gt;
&lt;br /&gt;
           $htmlcode .= &amp;quot;&amp;gt;&amp;quot;.getLanguageNameFromCode($key,false).&amp;quot;&amp;lt;/option&amp;gt;\n&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       $htmlcode .= &amp;quot;&amp;lt;/select&amp;gt;\n&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Basically it just pre-selects the base language from the list.&lt;/div&gt;</summary>
		<author><name>Mdekker</name></author>
	</entry>
	<entry>
		<id>https://www.limesurvey.org/manual/index.php?title=Coding_guidelines&amp;diff=43751</id>
		<title>Coding guidelines</title>
		<link rel="alternate" type="text/html" href="https://www.limesurvey.org/manual/index.php?title=Coding_guidelines&amp;diff=43751"/>
		<updated>2013-06-28T09:47:13Z</updated>

		<summary type="html">&lt;p&gt;Mdekker: Reverted edits by Sammousa (talk) to last revision by Jweberhofer&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
Contents:__TOC__&lt;br /&gt;
&lt;br /&gt;
=General=&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;This is a free development, everything you do can be useful for others. If the feature is very personal there is a way to turn it into a universal solution. This is the challenge!&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;simplebox&amp;quot;&amp;gt;&amp;quot;The difficulty within a solution is to solve it in a simple way&amp;quot;&lt;br /&gt;
&lt;br /&gt;
(Lance Burton, magician)&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Some general rules:&lt;br /&gt;
*Be efficient and save resources (memory and runtime). Things might work for a small survey but also try out your new feature with a survey that has 400 question, 5 languages and 20,000 responses (Yes, there are surveys like this out there).&lt;br /&gt;
*Keep a fluid dialog with the others coders, they have their own thoughts about what you are doing.&lt;br /&gt;
*Ask if you are in doubt.&lt;br /&gt;
&lt;br /&gt;
=Naming convention=&lt;br /&gt;
*Use the Hungarian Rule for variables:&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;
[t]NameOfVariable&lt;br /&gt;
&lt;br /&gt;
 | &amp;lt;strike&amp;gt;-&amp;lt;/strike&amp;gt;&amp;lt;strike&amp;gt;+&amp;lt;/strike&amp;gt;----&lt;br /&gt;
&lt;br /&gt;
 |        +--&amp;gt; Descriptive name&lt;br /&gt;
&lt;br /&gt;
 +--&amp;gt; Datatype stored (for example start with &amp;quot;a&amp;quot; if it is an array)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
aQuestionAttributes: Array to store the questions attributes, Mixed values&lt;br /&gt;
&lt;br /&gt;
dSurveyEnds: Date when the survey ends&lt;br /&gt;
&lt;br /&gt;
sContditionsOutput: String used to create the JS for conditions&lt;br /&gt;
*In case a function is declared &#039;&#039;&#039;do not&#039;&#039;&#039; use the Hungarian rule for the function name, instead use &amp;quot;Lower CamelCase&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
function questionsRetrieve( $iQID, $iSurvey)&lt;br /&gt;
*What about files? Unless Yii requires it in some way always name your files in lowercase - this prevents problems on systems using case-aware filesystems&lt;br /&gt;
&lt;br /&gt;
Here a list of prefixes:&lt;br /&gt;
*o=Object&lt;br /&gt;
*a=Array&lt;br /&gt;
*i=Integer&lt;br /&gt;
*f=Float&lt;br /&gt;
*s=String&lt;br /&gt;
&lt;br /&gt;
=Documentation=&lt;br /&gt;
&lt;br /&gt;
Please refer to this introduction: [[How to document your source code]].&lt;br /&gt;
&lt;br /&gt;
=Structures=&lt;br /&gt;
*Indent using spaces instead of TAB, or be gentle to announce how many spaces are your TABs long. There is wide ranging debate about tabs vs. spaces, many people prefer using tabs, others prefer spaces, others are happy with a mix of tabs and spaces. Because LimeSurvey is developed collaboratively, we ask that you leave your preference and follow this standard.&lt;br /&gt;
*The opening curly brace must be below the structure opening:&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;
if (condition)&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;
*Using one line for a simple condition is very &amp;quot;fashionable&amp;quot;, a taste of &amp;quot;hacker&amp;quot;, but it is not clear at all:&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;
 WRONG: if (condition) {do true} else {do false}&lt;br /&gt;
&lt;br /&gt;
 WRONG: if (condition) {do true}&lt;br /&gt;
&lt;br /&gt;
        else {do false}&lt;br /&gt;
&lt;br /&gt;
 RIGHT: if (condition)&lt;br /&gt;
&lt;br /&gt;
        {&lt;br /&gt;
&lt;br /&gt;
           do true&lt;br /&gt;
&lt;br /&gt;
        } else&lt;br /&gt;
&lt;br /&gt;
        {&lt;br /&gt;
&lt;br /&gt;
           do false&lt;br /&gt;
&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
 RIGHT: swith $sSelector&lt;br /&gt;
&lt;br /&gt;
        {&lt;br /&gt;
&lt;br /&gt;
              case X:&lt;br /&gt;
&lt;br /&gt;
                   ...&lt;br /&gt;
&lt;br /&gt;
                   break;&lt;br /&gt;
&lt;br /&gt;
              case Y:&lt;br /&gt;
&lt;br /&gt;
                   ...&lt;br /&gt;
&lt;br /&gt;
              default:&lt;br /&gt;
&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
NOTE: It&amp;amp;acute;s true that sometimes the &amp;quot;WRONG&amp;quot; way can be useful, but if it makes the straight reading difficult, please use the &amp;quot;RIGHT&amp;quot; way instead. Be gentle with your fellow developers.&lt;br /&gt;
*SQL sentences must respect the same rule:&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;
 $sSQL = &amp;quot;SELECT field1, field2, field3 &amp;quot;&lt;br /&gt;
&lt;br /&gt;
        .&amp;quot;WHERE condition &amp;quot;&lt;br /&gt;
&lt;br /&gt;
        .&amp;quot;AND condition &amp;quot;&lt;br /&gt;
&lt;br /&gt;
        .&amp;quot;OR condition &amp;quot;&lt;br /&gt;
&lt;br /&gt;
        .&amp;quot;ORDER BY field1, field2&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
*The same for HTML in views tags:&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;
&amp;lt;table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;td colspan=&#039;2&#039;&lt;br /&gt;
&lt;br /&gt;
     height=&#039;4&#039;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;strong&amp;gt;&lt;br /&gt;
&lt;br /&gt;
   Some Text&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;/strong&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;/td&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=HTML=&lt;br /&gt;
*As you will notice, a very customized HTML element can take a lot of lines (very expensive if you paid each one (:wink:) ) to avoid that, use &#039;CSS classes&#039;. In general, use classes to aesthetic related stuff: color, borders, backgrounds, font faces, sizes, etc.&lt;br /&gt;
*Respect W3C standards, and try to use the HTML understandable for all browsers. If one of them has a special feature, think if this feature is so special to break down the HTML in other browsers.&lt;br /&gt;
*Do not use PHP short tags &amp;lt;? ?&amp;gt;. Always use full PHP tags &amp;lt;?php ?&amp;gt;&lt;br /&gt;
*Any rules of the mentioned before: about CSS, well closed HTML tags and JS respect XHTML standards. Give it a try!.&lt;br /&gt;
&lt;br /&gt;
=Localization=&lt;br /&gt;
&lt;br /&gt;
Currently we are using the gT(),eT(),ngT() and neT() functions of the limesurvey_lang object for translations.&lt;br /&gt;
&lt;br /&gt;
Since LimeSurvey is available in 60 languages it is very important that your original English string (which will be picked up automatically for translation by our translators) is done right from the start. Imagine if we have to correct only one string at a later time - then 60 strings become invalid across the project and need to be re-translated by the poor translator souls.&lt;br /&gt;
* gT() is the original translation function. It will return a translated version of the string in the currently selected language. ie: echo &#039;&#039;$clang-&amp;gt;gT(&amp;quot;Hello&amp;quot;);&#039;&#039;&lt;br /&gt;
* ngT() returns multiple translations of a sentence or phrase for which alternate plural forms may apply. ie: &#039;&#039;echo sprintf($clang-&amp;gt;ngT(&#039;Please select at least %s answer&#039;,&#039;Please select at least %s answers&#039;,iMinimumAnswers),$iMinimumAnswers)&#039;&#039;;&lt;br /&gt;
* eT() echos the translation directly. (ie: instead of &#039;&#039;echo $clang-&amp;gt;gT(&amp;quot;Hello&amp;quot;);&#039;&#039; you can use &#039;&#039;$clang-&amp;gt;eT(&amp;quot;Hello&amp;quot;);&#039;&#039;&lt;br /&gt;
* neT() echos the multiple translations of the sentence or phrase for which alternate plural forms may apply directly.&lt;br /&gt;
&lt;br /&gt;
Please follow these important rules:&lt;br /&gt;
*&#039;&#039;&#039;Do not embed margin spaces&#039;&#039;&#039; in your translation. Instead use proper CSS formatting&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span style=&#039;color:#F00&#039;&amp;gt;Wrong&amp;lt;/span&amp;gt;: $clang-&amp;gt;eT(&#039;Visible? &#039;);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span style=&#039;color:#060&#039;&amp;gt;Right&amp;lt;/span&amp;gt;: $clang-&amp;gt;eT(&#039;Visible?&#039;);&lt;br /&gt;
*&#039;&#039;&#039;Do not capitalize words&#039;&#039;&#039; except where grammatically correct (like at the beginning of a sentence or for a brand name). LimeSurvey is not a newspaper.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span style=&#039;color:#F00&#039;&amp;gt;Wrong&amp;lt;/span&amp;gt;: $clang-&amp;gt;eT(&#039;Create A New Label Set&#039;);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span style=&#039;color:#060&#039;&amp;gt;Right&amp;lt;/span&amp;gt;: $clang-&amp;gt;eT(&#039;Create a new label set&#039;);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span style=&#039;color:#F00&#039;&amp;gt;Wrong&amp;lt;/span&amp;gt;: $clang-&amp;gt;eT(&#039;Google Maps API Key&#039;);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span style=&#039;color:#060&#039;&amp;gt;Right&amp;lt;/span&amp;gt;: $clang-&amp;gt;eT(&#039;Google Maps API key&#039;);&lt;br /&gt;
*&#039;&#039;&#039;Do not concatenate&#039;&#039;&#039; several translations to form a sentence or concatenate to an additional information (like a number or string). Instead use the sprint() or sprintf() function with placeholders.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span style=&#039;color:#F00&#039;&amp;gt;Wrong&amp;lt;/span&amp;gt;: echo $clang-&amp;gt;gT(&#039;The sum must not be bigger than&#039;).$iMaxSum;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span style=&#039;color:#060&#039;&amp;gt;Right&amp;lt;/span&amp;gt;: echo sprintf($clang-&amp;gt;gT(&#039;The sum must not be bigger than %s&#039;),$iMaxSum);&lt;br /&gt;
&lt;br /&gt;
This comes from the problem that in other languages the setting of a sentence can be much different and the information $iMaxSum from the example above might be needed in the middle of the sentence.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span style=&#039;color:#F00&#039;&amp;gt;Wrong&amp;lt;/span&amp;gt;: echo $clang-&amp;gt;gT(&#039;The user&#039;).$sUsername.$clang-&amp;gt;gT(&#039;was deleted.&#039;);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span style=&#039;color:#060&#039;&amp;gt;Right&amp;lt;/span&amp;gt;: echo sprintf($clang-&amp;gt;gT(&#039;The user %s was deleted.&#039;),$sUsername);&lt;br /&gt;
*&#039;&#039;&#039;Use the n*T functions where applicable&#039;&#039;&#039;. These functions show a different translation depending the number of items. Currently LimeSurvey only supports the numbers/situations 1 and &amp;gt;1.&lt;br /&gt;
&lt;br /&gt;
+Example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span style=&#039;color:#F00&#039;&amp;gt;Wrong&amp;lt;/span&amp;gt;: echo sprintf($clang-&amp;gt;gT(&#039;Please select at least %s answer(s).&#039;),$iMinimumAnswers);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span style=&#039;color:#060&#039;&amp;gt;Right&amp;lt;/span&amp;gt;: echo sprintf($clang-&amp;gt;ngT(&#039;Please select at least %s answer&#039;,&#039;Please select at least %s answers&#039;,iMinimumAnswers),$iMinimumAnswers);&lt;br /&gt;
&lt;br /&gt;
=Bug tracker=&lt;br /&gt;
#First consider if the reported issue is really a bug. If it is a feature request please point the reporter to http://ideas.limesurvey.org and set the issue status to &#039;Closed&#039;.&lt;br /&gt;
#If you would like to work on a bug assign it to yourself.&lt;br /&gt;
#Try to reproduce the issue.&lt;br /&gt;
##If you cannot reproduce ask the user to provide a small example survey to demonstrate the issue. Then set the issue to &#039;Feedback&#039;. After the user added the necessary information it will automatically be set to &#039;Assigned&#039; again.&lt;br /&gt;
##If the user does not responds for more than a week ask once again for feedback by adding a comment. After a further week without feedback close the issue.&lt;br /&gt;
#After you resolved the issue set the status to resolved AND provide the &#039;Fixed in version&#039; information.&lt;br /&gt;
#After you committed your fix add a comment to the resolved issue &#039;Fixed in rev. &amp;lt;Subversion revision number&amp;gt;&#039;&lt;br /&gt;
#After a release the release technician will set all issues to &#039;Closed&#039; that were fixed for this release. That signals to the reporter that a fix is available in the version and it was just released.&lt;br /&gt;
&lt;br /&gt;
=Cross-DB compatibility=&lt;br /&gt;
&lt;br /&gt;
LimeSurvey targets several database types it can run on: MySQL, Postgres and Microsoft SQL Server. This demands certain precautions when coding&lt;br /&gt;
&lt;br /&gt;
==Parameter binding==&lt;br /&gt;
&lt;br /&gt;
Yii/PDO supports parameter binding - use it. Don&#039;t inject variables directly into the query or into conditions because this might create a security issue.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
$oResult = Yii::app()-&amp;gt;db&lt;br /&gt;
&lt;br /&gt;
                    -&amp;gt;createCommand()&lt;br /&gt;
&lt;br /&gt;
                    -&amp;gt;select(&#039;somefield&#039;)&lt;br /&gt;
&lt;br /&gt;
                    -&amp;gt;where(&amp;quot;sid = :sid&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
                    -&amp;gt;from(&#039;{{sometable}}&#039;)&lt;br /&gt;
&lt;br /&gt;
                    -&amp;gt;bindParam(&amp;quot;:sid&amp;quot;, $surveyid, PDO::PARAM_INT);&lt;br /&gt;
&lt;br /&gt;
?&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you bind the same value several times do NOT use the same parameter name, instead use a different named parameter for each bind:&lt;br /&gt;
&lt;br /&gt;
WRONG:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
$oResult = Yii::app()-&amp;gt;db&lt;br /&gt;
&lt;br /&gt;
                    -&amp;gt;createCommand()&lt;br /&gt;
&lt;br /&gt;
                    -&amp;gt;select(&#039;somefield&#039;)&lt;br /&gt;
&lt;br /&gt;
                    -&amp;gt;where(&amp;quot;sid = :sid and parent_sid= :sid &amp;quot;)&lt;br /&gt;
&lt;br /&gt;
                    -&amp;gt;from(&#039;{{sometable}}&#039;)&lt;br /&gt;
&lt;br /&gt;
                    -&amp;gt;bindParam(&amp;quot;:sid&amp;quot;, $surveyid, PDO::PARAM_INT);&lt;br /&gt;
&lt;br /&gt;
?&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
RIGHT:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
$oResult = Yii::app()-&amp;gt;db&lt;br /&gt;
&lt;br /&gt;
                    -&amp;gt;createCommand()&lt;br /&gt;
&lt;br /&gt;
                    -&amp;gt;select(&#039;somefield&#039;)&lt;br /&gt;
&lt;br /&gt;
                    -&amp;gt;where(&amp;quot;sid = :sid1 and parent_sid= :sid2 &amp;quot;)&lt;br /&gt;
&lt;br /&gt;
                    -&amp;gt;from(&#039;{{sometable}}&#039;)&lt;br /&gt;
&lt;br /&gt;
                    -&amp;gt;bindParam(&amp;quot;:sid1&amp;quot;, $surveyid, PDO::PARAM_INT)&lt;br /&gt;
&lt;br /&gt;
                    -&amp;gt;bindParam(&amp;quot;:sid2&amp;quot;, $surveyid, PDO::PARAM_INT);&lt;br /&gt;
&lt;br /&gt;
?&amp;gt;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Miscellaneous=&lt;br /&gt;
*Do not use &amp;quot;global&amp;quot; to access to a declared variable in another process. Pass variables or arrays by reference, use the session or the configuration object.&lt;br /&gt;
*If using an auxiliary variable makes clear the code or process, just do it. If you are coding a very complex expression, calling to functions with parameters that are other functions:&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;
WRONG:&lt;br /&gt;
&lt;br /&gt;
iAResult= fa(fb(p1,p2),fc(fd(p3),p4),p5)&lt;br /&gt;
&lt;br /&gt;
It will be more readable:&lt;br /&gt;
&lt;br /&gt;
iAuxB = fb(p1,p2)&lt;br /&gt;
&lt;br /&gt;
iAuxD = fd(p3)&lt;br /&gt;
&lt;br /&gt;
iAuxC = fc(iAuxD,p4)&lt;br /&gt;
&lt;br /&gt;
iAResult = fa(iAuxB, iAuxC, p5)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Anyway, if you are in doubt about someone missing the point or you are afraid that your expression is obscure, take the chance of writing it in a more simple way, even if that involves the use of one or more auxiliary variables.&lt;br /&gt;
&lt;br /&gt;
[[Category:Development]]&lt;/div&gt;</summary>
		<author><name>Mdekker</name></author>
	</entry>
	<entry>
		<id>https://www.limesurvey.org/manual/index.php?title=RemoteControl_2_API&amp;diff=43750</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=43750"/>
		<updated>2013-06-28T09:43:52Z</updated>

		<summary type="html">&lt;p&gt;Mdekker: &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 later. The old [RemoteControl] will not be available any longer in version 2.&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;Services&#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 the following functions:&lt;br /&gt;
&lt;br /&gt;
==get_session_key==&lt;br /&gt;
&lt;br /&gt;
Using this function you can create a new XML-RPC session key. This is mandatory for all following LSRC2 function calls.&lt;br /&gt;
&lt;br /&gt;
Parameters: username (string), password (string)&lt;br /&gt;
&lt;br /&gt;
Returns:&lt;br /&gt;
*On success: A session key (string)&lt;br /&gt;
*On failure:  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;
Parameters: session key (string)&lt;br /&gt;
&lt;br /&gt;
Returns:&lt;br /&gt;
*Always: &#039;OK&#039; (string)&lt;br /&gt;
&lt;br /&gt;
==get_site_settings==&lt;br /&gt;
&lt;br /&gt;
Function to provide with site settings only to administrators&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
&lt;br /&gt;
sSessionKey (string) The session key&lt;br /&gt;
&lt;br /&gt;
sSetttingName (string) -  Name of the setting to get&lt;br /&gt;
&lt;br /&gt;
Returns:&lt;br /&gt;
*On success: (string) Setting&lt;br /&gt;
*On failure: (string) Error message&lt;br /&gt;
&lt;br /&gt;
==add_survey==&lt;br /&gt;
&lt;br /&gt;
RPC Routine to add an empty survey with minimum details&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
&lt;br /&gt;
sSessionKey (string)  Auth credentials&lt;br /&gt;
&lt;br /&gt;
iSurveyID     (int),    The wish id of the Survey to add&lt;br /&gt;
&lt;br /&gt;
sSurveyTitle     (string),  Title of the new Survey&lt;br /&gt;
&lt;br /&gt;
sSurveyLanguage    (string),  Default language of the Survey&lt;br /&gt;
&lt;br /&gt;
sformat     (string),  Question appearance format (S|G|A)&lt;br /&gt;
&lt;br /&gt;
Returns:&lt;br /&gt;
*On success: (int) $iNewSurveyID&lt;br /&gt;
*On failure: (array) Failure status&lt;br /&gt;
**Invalid session key&lt;br /&gt;
**No permission&lt;br /&gt;
**Faulty parameters&lt;br /&gt;
**Creation Failed&lt;br /&gt;
&lt;br /&gt;
==delete_survey==&lt;br /&gt;
&lt;br /&gt;
RPC Routine to Delete a survey&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
&lt;br /&gt;
sSessionKey (string), Auth credentials&lt;br /&gt;
&lt;br /&gt;
iSurveyID (int), The Survey to delete&lt;br /&gt;
&lt;br /&gt;
Returns:&lt;br /&gt;
*On success: Status =&amp;gt;OK (array)&lt;br /&gt;
*On failure: (array) Failure status&lt;br /&gt;
**Invalid session key&lt;br /&gt;
**No permission&lt;br /&gt;
&lt;br /&gt;
==import_survey==&lt;br /&gt;
&lt;br /&gt;
RPC Routine to import a survey from lss,csv,xls or survey zip archive.&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
&lt;br /&gt;
sSessionKey (string)  Auth credentials&lt;br /&gt;
&lt;br /&gt;
sImportData  (string) String containing the BASE 64 encoded data of a lss,csv,xls or survey zip archive&lt;br /&gt;
&lt;br /&gt;
sImportDataType     (string),    The format of the import file (lss,csv,xls or zip)&lt;br /&gt;
&lt;br /&gt;
sNewSurveyName     (string),  The optional new name of the survey (base language)&lt;br /&gt;
&lt;br /&gt;
DestSurveyID    (int), This is the new ID of the survey - if already used a random one will be taken instead&lt;br /&gt;
&lt;br /&gt;
Returns:&lt;br /&gt;
*On success: (int) $iNewSurveyID&lt;br /&gt;
*On failure: (array) Failure status&lt;br /&gt;
**Invalid session key&lt;br /&gt;
**No permission&lt;br /&gt;
**Import error&lt;br /&gt;
&lt;br /&gt;
==get_survey_properties==&lt;br /&gt;
&lt;br /&gt;
RPC Routine to get properties of a survey&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
&lt;br /&gt;
sSessionKey (string)  Auth credentials&lt;br /&gt;
&lt;br /&gt;
iSurveyID (integer) -  ID of the survey&lt;br /&gt;
&lt;br /&gt;
aSurveySettings     (array),    An array with the properties to return&lt;br /&gt;
&lt;br /&gt;
Returns:&lt;br /&gt;
*On success: (string) the requested value&lt;br /&gt;
*On failure: (array) Failure status&lt;br /&gt;
**Invalid survey ID&lt;br /&gt;
**Invalid session key&lt;br /&gt;
**No permission&lt;br /&gt;
**No valid Data&lt;br /&gt;
&lt;br /&gt;
Available properties:&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|   ||   ||   ||   ||   ||&lt;br /&gt;
|-&lt;br /&gt;
|   sid||   savetimings||   allowprev||   tokenanswerspersistence||   showgroupinfo||   showwelcome&lt;br /&gt;
|-&lt;br /&gt;
|   owner_id||   template||   printanswers||   assessments||  shownoanswer ||   showprogress&lt;br /&gt;
|-&lt;br /&gt;
|   admin||   language||   ipaddr||   usecaptcha||   showqnumcode||   allowjumps&lt;br /&gt;
|-&lt;br /&gt;
|   active||   additional_languages ||   refurl||   usetokens||   bouncetime||   navigationdelay&lt;br /&gt;
|-&lt;br /&gt;
|   expires||   datestamp||   datecreated||   bounce_email||   bounceprocessing||   nokeyboard&lt;br /&gt;
|-&lt;br /&gt;
|   startdate||   usecookie||   publicstatistics||   attributedescriptions||   bounceaccounttype||   alloweditaftercompletion&lt;br /&gt;
|-&lt;br /&gt;
|   adminemail||   allowregister||   publicgraphs||   emailresponseto||   bounceaccounthost||   googleanalyticsstyle&lt;br /&gt;
|-&lt;br /&gt;
|   anonymized||   allowsave||   listpublic||   emailnotificationto||   bounceaccountpass||   googleanalyticsapikey&lt;br /&gt;
|-&lt;br /&gt;
|   faxto||   autonumber_start||   htmlemail||   tokenlength||   bounceaccountencryption||&lt;br /&gt;
|-&lt;br /&gt;
|format||   autoredirect||   sendconfirmation||   showxquestions||   bounceaccountuser||   &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==set_survey_properties==&lt;br /&gt;
&lt;br /&gt;
RPC Routine to set properties of a survey&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
&lt;br /&gt;
sSessionKey (string)  Auth credentials&lt;br /&gt;
&lt;br /&gt;
iSurveyID (integer) -  ID of the survey&lt;br /&gt;
&lt;br /&gt;
aSurveySettings     (array),    An assosiative array with the name-value  pair of the properties to set&lt;br /&gt;
&lt;br /&gt;
Returns:&lt;br /&gt;
*On success: (array) The result of the change for each property&lt;br /&gt;
*On failure: (array) Failure status&lt;br /&gt;
**Invalid survey ID&lt;br /&gt;
**Invalid session key&lt;br /&gt;
**No permission&lt;br /&gt;
**No valid Data&lt;br /&gt;
&lt;br /&gt;
Available properties:&lt;br /&gt;
&lt;br /&gt;
Properties available for changing are all those defined in get_survey_properties with the following exceptions&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|properties not allowed to be modified|| Properties not allowed to be modified when survey active&lt;br /&gt;
|-&lt;br /&gt;
|sid||anonymized&lt;br /&gt;
|-&lt;br /&gt;
|language||datestamp&lt;br /&gt;
|-&lt;br /&gt;
|additional_languages||savetimings&lt;br /&gt;
|-&lt;br /&gt;
|active||ipaddr&lt;br /&gt;
|-&lt;br /&gt;
|||refurl&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==list_surveys==&lt;br /&gt;
&lt;br /&gt;
RPC Routine to list the ids and info of surveys belonging to a user.&lt;br /&gt;
&lt;br /&gt;
    * If user is admin he can get surveys of every user (parameter sUser) or all surveys (sUser=null)&lt;br /&gt;
&lt;br /&gt;
    * Else only the syrveys belonging to the user requesting will be shown.&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
&lt;br /&gt;
sSessionKey (string)  Auth credentials&lt;br /&gt;
&lt;br /&gt;
sUser (string) -  The users surveys to list&lt;br /&gt;
&lt;br /&gt;
Returns:&lt;br /&gt;
*On success: (array) Survey&#039;s properties&lt;br /&gt;
*On failure: (array) Failure status&lt;br /&gt;
**Invalid user&lt;br /&gt;
**Invalid session key&lt;br /&gt;
**No permission&lt;br /&gt;
**No surveys found&lt;br /&gt;
&lt;br /&gt;
Survey&#039;s properties:&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|property||type&lt;br /&gt;
|-&lt;br /&gt;
|sid||integer&lt;br /&gt;
|-&lt;br /&gt;
|surveyls_title||string&lt;br /&gt;
|-&lt;br /&gt;
|startdate||date&lt;br /&gt;
|-&lt;br /&gt;
|expires||date&lt;br /&gt;
|-&lt;br /&gt;
|active||y/n&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==activate_survey==&lt;br /&gt;
&lt;br /&gt;
RPC Routine that launches a newly created survey (sets active -available for users)&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
&lt;br /&gt;
sSessionKey (string)  Auth credentials&lt;br /&gt;
&lt;br /&gt;
SurveyID (integer) -  ID of the survey&lt;br /&gt;
&lt;br /&gt;
Returns&lt;br /&gt;
*On success: (array) The result of the activation&lt;br /&gt;
*On failure: (array) Failure status&lt;br /&gt;
**Invalid Survey ID&lt;br /&gt;
**Activation Error&lt;br /&gt;
**Invalid session key&lt;br /&gt;
**No permission&lt;br /&gt;
&lt;br /&gt;
==export_statistics==&lt;br /&gt;
&lt;br /&gt;
RPC routine to export statistics of a survey to a user.&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
&lt;br /&gt;
sSessionKey (string)  Auth credentials&lt;br /&gt;
&lt;br /&gt;
SurveyID (integer) -  ID of the survey&lt;br /&gt;
&lt;br /&gt;
docType (string) - Type of document to generate&lt;br /&gt;
&lt;br /&gt;
sLanguage (string) Optional language of the survey to use (if not set, default language is selected)&lt;br /&gt;
&lt;br /&gt;
graph (string) - Optional parameter to enable graphs (0|1)&lt;br /&gt;
&lt;br /&gt;
Returns&lt;br /&gt;
*On success: (string) Base64 encoded string with the statistics file&lt;br /&gt;
*On failure: (array) Failure status&lt;br /&gt;
**Invalid Survey ID&lt;br /&gt;
**Invalid session key&lt;br /&gt;
**No permission&lt;br /&gt;
&lt;br /&gt;
==get_summary==&lt;br /&gt;
&lt;br /&gt;
RPC routine to get survey summary, regarding token usage and survey participation.&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
&lt;br /&gt;
sSessionKey (string) - Auth credentials&lt;br /&gt;
&lt;br /&gt;
iSurveyID (integer) -  ID of the survey&lt;br /&gt;
&lt;br /&gt;
sStatname (string) - The statistic to return&lt;br /&gt;
&lt;br /&gt;
Returns&lt;br /&gt;
*On success: (string) Base64 encoded string with the statistics file&lt;br /&gt;
*On failure: (array) Failure status&lt;br /&gt;
**No available data&lt;br /&gt;
**No such property&lt;br /&gt;
**Invalid session key&lt;br /&gt;
**No permission&lt;br /&gt;
&lt;br /&gt;
Available statistics:&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|Survey stats||Token stats&lt;br /&gt;
|-&lt;br /&gt;
|completed_responses||token_count&lt;br /&gt;
|-&lt;br /&gt;
|incomplete_responses||token_invalid&lt;br /&gt;
|-&lt;br /&gt;
|full_responses||tokens_sent&lt;br /&gt;
|-&lt;br /&gt;
|||token_opted_out&lt;br /&gt;
|-&lt;br /&gt;
|||token_completed&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==add_language==&lt;br /&gt;
&lt;br /&gt;
RPC Routine to add a language to an existing survey&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
&lt;br /&gt;
session key (string) - The session key&lt;br /&gt;
&lt;br /&gt;
SurveyID (integer) -  ID of the survey&lt;br /&gt;
&lt;br /&gt;
aLanguage (string) - The language shortcut for the new language to be added. Note: If the language is already in that survey no error will be thrown.&lt;br /&gt;
&lt;br /&gt;
Return values:&lt;br /&gt;
*On success: (array) status=&amp;gt;OK&lt;br /&gt;
*On failure: (array) Any other status&lt;br /&gt;
**Invalid survey ID&lt;br /&gt;
**Invalid language&lt;br /&gt;
**Error&lt;br /&gt;
**Invalid session key&lt;br /&gt;
**No permission&lt;br /&gt;
&lt;br /&gt;
==delete_survey_language==&lt;br /&gt;
&lt;br /&gt;
RPC Routine to delete a language of an existing survey&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
&lt;br /&gt;
session key (string) The session key&lt;br /&gt;
&lt;br /&gt;
SurveyID (integer) -  ID of the survey&lt;br /&gt;
&lt;br /&gt;
aLanguage (string) - The language shortcut for the language to be removed. Note: If the language is not part of that survey no error will be thrown.&lt;br /&gt;
&lt;br /&gt;
Return values:&lt;br /&gt;
*On success: (array) status=&amp;gt;OK&lt;br /&gt;
*On failure: (array) Any other status&lt;br /&gt;
**Invalid survey ID&lt;br /&gt;
**Invalid language&lt;br /&gt;
**Cannot remove base language&lt;br /&gt;
**Error&lt;br /&gt;
**No permission&lt;br /&gt;
**Invalid session key&lt;br /&gt;
&lt;br /&gt;
==get_language_properties==&lt;br /&gt;
&lt;br /&gt;
RPC Routine to get survey language properties&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
&lt;br /&gt;
sSessionKey (string) - Auth credentials&lt;br /&gt;
&lt;br /&gt;
iSurveyID (integer) -  ID of the survey&lt;br /&gt;
&lt;br /&gt;
aSurveyLocaleSettings     (array) -  An array with the properties to return&lt;br /&gt;
&lt;br /&gt;
slang (string)    - The language to use&lt;br /&gt;
&lt;br /&gt;
Returns:&lt;br /&gt;
*On success: (string) the requested value&lt;br /&gt;
*On failure: (array) Failure status&lt;br /&gt;
**Invalid survey ID&lt;br /&gt;
**Invalid session key&lt;br /&gt;
**No permission&lt;br /&gt;
**No valid Data&lt;br /&gt;
&lt;br /&gt;
Available parameters:&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|   ||   ||   ||&lt;br /&gt;
|-&lt;br /&gt;
|    surveyls_survey_id            ||    surveyls_url                  ||    surveyls_email_register_subj  ||    email_admin_notification_subj&lt;br /&gt;
|-&lt;br /&gt;
|    surveyls_language             ||    surveyls_urldescription       ||    surveyls_email_register       ||    email_admin_notification&lt;br /&gt;
|-&lt;br /&gt;
|    surveyls_title                ||    surveyls_email_invite_subj    ||    surveyls_email_confirm_subj   ||    email_admin_responses_subj&lt;br /&gt;
|-&lt;br /&gt;
|    surveyls_description          ||    surveyls_email_invite         ||    surveyls_email_confirm        ||    email_admin_responses&lt;br /&gt;
|-&lt;br /&gt;
|    surveyls_welcometext          || surveyls_email_remind_subj       ||    surveyls_dateformat           ||    surveyls_numberformat&lt;br /&gt;
|-&lt;br /&gt;
|surveyls_endtext              ||    surveyls_email_remind         ||    surveyls_attributecaptions    ||   &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==set_language_properties==&lt;br /&gt;
&lt;br /&gt;
RPC Routine to set survey language properties&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
&lt;br /&gt;
sSessionKey (string) - Auth credentials&lt;br /&gt;
&lt;br /&gt;
iSurveyID (integer) -  ID of the survey&lt;br /&gt;
&lt;br /&gt;
aSurveyLocaleData     (array) -  An assosiative array with the key-value pairs of properties to set. Invalid fieldnames or fields that may not be modified are ignored.&lt;br /&gt;
&lt;br /&gt;
sLanguage (string)    - The language to use&lt;br /&gt;
&lt;br /&gt;
Returns:&lt;br /&gt;
*On success: (string) Result for each parameter set&lt;br /&gt;
*On failure: (array) Failure status&lt;br /&gt;
**Invalid survey ID&lt;br /&gt;
**Invalid language&lt;br /&gt;
**Invalid session key&lt;br /&gt;
**No permission&lt;br /&gt;
**No valid Data&lt;br /&gt;
&lt;br /&gt;
Allowed Parameters:&lt;br /&gt;
&lt;br /&gt;
All those defined in get-language_properties except:&lt;br /&gt;
*surveyls_language&lt;br /&gt;
*surveyls_survey_id&lt;br /&gt;
&lt;br /&gt;
==add_group==&lt;br /&gt;
&lt;br /&gt;
RPC Routine to add an empty group with minimum details.&lt;br /&gt;
&lt;br /&gt;
    * Used as a placeholder for importing questions.&lt;br /&gt;
&lt;br /&gt;
    * Returns the groupid of the created group.&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
&lt;br /&gt;
sSessionKey (string) - Auth credentials&lt;br /&gt;
&lt;br /&gt;
iSurveyID (integer) -  ID of the surveythat the group will be added&lt;br /&gt;
&lt;br /&gt;
sGroupTitle     (string) -  Name of the new group&lt;br /&gt;
&lt;br /&gt;
sGroupDescription (string) - Optional description of the group&lt;br /&gt;
&lt;br /&gt;
Returns:&lt;br /&gt;
*On success: (int) The ID of the new group&lt;br /&gt;
*On failure: (array) Failure status&lt;br /&gt;
**Invalid survey ID&lt;br /&gt;
**Error:Survey is active and not editable&lt;br /&gt;
**Invalid session key&lt;br /&gt;
**No permission&lt;br /&gt;
**Creation Failed&lt;br /&gt;
&lt;br /&gt;
==delete_group==&lt;br /&gt;
&lt;br /&gt;
RPC Routine to delete a group of a survey&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
&lt;br /&gt;
sSessionKey (string) - Auth credentials&lt;br /&gt;
&lt;br /&gt;
iSurveyID (integer) -  ID of the survey that the group belongs&lt;br /&gt;
&lt;br /&gt;
sGroupID    (int) -  Id of the group to delete&lt;br /&gt;
&lt;br /&gt;
Returns:&lt;br /&gt;
*On success: (int) The ID of the deleted group&lt;br /&gt;
*On failure: (array) Failure status&lt;br /&gt;
**Invalid Survey ID&lt;br /&gt;
**Invalid Group ID&lt;br /&gt;
**Error:Survey is active and not editable&lt;br /&gt;
**Invalid session key&lt;br /&gt;
**No permission&lt;br /&gt;
**Group deletion failed&lt;br /&gt;
&lt;br /&gt;
==import_group==&lt;br /&gt;
&lt;br /&gt;
RPC Routine to import a group - imports lsg,csv&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
&lt;br /&gt;
sSessionKey (string) - Auth credentials&lt;br /&gt;
&lt;br /&gt;
iSurveyID (integer) -  The id of the survey that the group will belong&lt;br /&gt;
&lt;br /&gt;
sImportData     (string) -  String containing the BASE 64 encoded data of a lsg,csv&lt;br /&gt;
&lt;br /&gt;
sGroupDescription (string) -The format of the importfile in the stream (lsg|csv)&lt;br /&gt;
&lt;br /&gt;
sNewGroupName (string) - Optional new name for the group&lt;br /&gt;
&lt;br /&gt;
sNewGroupDescription (string) - Optional new description for the group&lt;br /&gt;
&lt;br /&gt;
Returns:&lt;br /&gt;
*On success: (int) The ID of the new group&lt;br /&gt;
*On failure: (array) Failure status&lt;br /&gt;
**Invalid survey ID&lt;br /&gt;
**Error:Survey is active and not editable&lt;br /&gt;
**Invalid extension&lt;br /&gt;
**Error: Invalid LimeSurvey group structure XML&lt;br /&gt;
**Invalid session key&lt;br /&gt;
**No permission&lt;br /&gt;
**Import Error&lt;br /&gt;
&lt;br /&gt;
==get_group_properties==&lt;br /&gt;
&lt;br /&gt;
RPC Routine to return properties of a group of a survey&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
&lt;br /&gt;
sSessionKey (string) - Auth credentials&lt;br /&gt;
&lt;br /&gt;
iGroupID (integer) -  The id of the group to get properties of&lt;br /&gt;
&lt;br /&gt;
aGroupSettings     (array) -  Array containing the properties to request.&lt;br /&gt;
&lt;br /&gt;
Returns:&lt;br /&gt;
*On success: (array) The requested properties&lt;br /&gt;
*On failure: (array) Failure status&lt;br /&gt;
**Error: Invalid group ID&lt;br /&gt;
**No valid Data&lt;br /&gt;
**Invalid session key&lt;br /&gt;
**No permission&lt;br /&gt;
&lt;br /&gt;
Available properties:&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| ||&lt;br /&gt;
|-&lt;br /&gt;
|gid||description&lt;br /&gt;
|-&lt;br /&gt;
|sid||language&lt;br /&gt;
|-&lt;br /&gt;
|group_name||randomization_group&lt;br /&gt;
|-&lt;br /&gt;
|group_order||grelevance&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==set_group_properties==&lt;br /&gt;
&lt;br /&gt;
RPC Routine to set properties of a group of a survey&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
&lt;br /&gt;
sSessionKey (string) - Auth credentials&lt;br /&gt;
&lt;br /&gt;
iGroupID (integer) -  The id of the group to set properties to&lt;br /&gt;
&lt;br /&gt;
aGroupData     (array) -  Assosiative Array containing key-value pairs of the properties to set.&lt;br /&gt;
&lt;br /&gt;
Returns:&lt;br /&gt;
*On success: (array) The result of each set action&lt;br /&gt;
*On failure: (array) Failure status&lt;br /&gt;
**Error: Invalid group ID&lt;br /&gt;
**No valid Data&lt;br /&gt;
**Group with dependencies - Order cannot be changed&lt;br /&gt;
**Invalid session key&lt;br /&gt;
**No permission&lt;br /&gt;
&lt;br /&gt;
Available properties:&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| ||&lt;br /&gt;
|-&lt;br /&gt;
|||description&lt;br /&gt;
|-&lt;br /&gt;
|||language&lt;br /&gt;
|-&lt;br /&gt;
|group_name||randomization_group&lt;br /&gt;
|-&lt;br /&gt;
|group_order||grelevance&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==list_groups==&lt;br /&gt;
&lt;br /&gt;
RPC Routine to return the ids and info of groups belonging to survey&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
&lt;br /&gt;
sSessionKey (string) - Auth credentials&lt;br /&gt;
&lt;br /&gt;
iSurveyID (integer) -  The id of the survey to get groups of&lt;br /&gt;
&lt;br /&gt;
Returns:&lt;br /&gt;
*On success: (array) The list of the groups&lt;br /&gt;
*On failure: (array) Failure status&lt;br /&gt;
**Invalid Survey ID&lt;br /&gt;
**No groups found&lt;br /&gt;
**Invalid session key&lt;br /&gt;
**No permission&lt;br /&gt;
&lt;br /&gt;
==delete_question==&lt;br /&gt;
&lt;br /&gt;
RPC Routine to delete a question of a survey&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
&lt;br /&gt;
sSessionKey (string)  Auth credentials&lt;br /&gt;
&lt;br /&gt;
iQuestionID  (int) Id of the question to delete&lt;br /&gt;
&lt;br /&gt;
Returns:&lt;br /&gt;
*On success: (int)id of the deleted Question&lt;br /&gt;
*On failure: (array) Failure status&lt;br /&gt;
**Invalid session key&lt;br /&gt;
**No permission&lt;br /&gt;
** Invalid question ID&lt;br /&gt;
**Survey is active and not editable&lt;br /&gt;
**Cannot delete Question. Others rely on this question&lt;br /&gt;
**Error&lt;br /&gt;
&lt;br /&gt;
==import_question==&lt;br /&gt;
&lt;br /&gt;
RPC Routine to import a question - imports lsq,csv&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
&lt;br /&gt;
sSessionKey (string) - Auth credentials&lt;br /&gt;
&lt;br /&gt;
iSurveyID  (int) - Id of the survey that the new questions belongs&lt;br /&gt;
&lt;br /&gt;
iGroupID (int) - Id of the group that the new questions belongs&lt;br /&gt;
&lt;br /&gt;
sImportData (string) - String containing the BASE 64 encoded data of a lsg,csv&lt;br /&gt;
&lt;br /&gt;
sImportDataType (string)  - Format of the input stream (lsq,csv)&lt;br /&gt;
&lt;br /&gt;
sMandatory (string) - Optional Mandatory question option (default to No)&lt;br /&gt;
&lt;br /&gt;
sNewQuestionTitle (string) - Optional new title for the question&lt;br /&gt;
&lt;br /&gt;
sNewqQuestion (string) - An optional new question&lt;br /&gt;
&lt;br /&gt;
sNewQuestionHelp (string) - An optional new question help text&lt;br /&gt;
&lt;br /&gt;
Returns:&lt;br /&gt;
*On success: (int) Id of the new Question&lt;br /&gt;
*On failure: (array) Failure status&lt;br /&gt;
**Invalid session key&lt;br /&gt;
**No permission&lt;br /&gt;
**Invalid survey ID&lt;br /&gt;
**Invalid group ID&lt;br /&gt;
**Survey is active and not editable&lt;br /&gt;
**Invalid extension&lt;br /&gt;
**Invalid LimeSurvey question structure XML&lt;br /&gt;
&lt;br /&gt;
==get_question_properties==&lt;br /&gt;
&lt;br /&gt;
RPC Routine to return properties of a question of a survey&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
&lt;br /&gt;
sSessionKey (string)  Auth credentials&lt;br /&gt;
&lt;br /&gt;
iQuestionID  (int) Id of the question to get properties of&lt;br /&gt;
&lt;br /&gt;
aQuestionSettings (array) The properties to get&lt;br /&gt;
&lt;br /&gt;
sLanguage (string) Optional parameter language for multilingual questions&lt;br /&gt;
&lt;br /&gt;
Returns:&lt;br /&gt;
*On success: (array) The requested properties&lt;br /&gt;
*On failure: (array) Failure status&lt;br /&gt;
**Invalid session key&lt;br /&gt;
**No permission&lt;br /&gt;
**Invalid questionid&lt;br /&gt;
**Invalid language&lt;br /&gt;
**No valid Data&lt;br /&gt;
&lt;br /&gt;
Available Properties:&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|  ||  ||  ||&lt;br /&gt;
|-&lt;br /&gt;
|gid||type||help||language&lt;br /&gt;
|-&lt;br /&gt;
|parent_qid||title||other||scale_id&lt;br /&gt;
|-&lt;br /&gt;
|sid||question||mandatory||same_default&lt;br /&gt;
|-&lt;br /&gt;
|gid||preg||question_order||relevance&lt;br /&gt;
|-&lt;br /&gt;
|subquestions||attributes||attributes_lang||answeroptions&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==set_question_properties==&lt;br /&gt;
&lt;br /&gt;
RPC Routine to set question properties&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
&lt;br /&gt;
sSessionKey (string) - Auth credentials&lt;br /&gt;
&lt;br /&gt;
iQuestionID  (int) - Id of the question to get properties of&lt;br /&gt;
&lt;br /&gt;
aQuestionData (array)  - An array with the particular fieldnames as keys and their values to set on that particular question&lt;br /&gt;
&lt;br /&gt;
sLanguage (string)  -  Optional parameter language for multilingual questions&lt;br /&gt;
&lt;br /&gt;
Returns:&lt;br /&gt;
*On success: (array) The resilt of the set of each property&lt;br /&gt;
*On failure: (array) Failure status&lt;br /&gt;
**Invalid session key&lt;br /&gt;
**No permission&lt;br /&gt;
**Invalid questionid&lt;br /&gt;
**Invalid language&lt;br /&gt;
**Questions with dependencies - Order cannot be changed&lt;br /&gt;
**No valid Data&lt;br /&gt;
&lt;br /&gt;
Available Properties:&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|  ||  ||&lt;br /&gt;
|-&lt;br /&gt;
|help|| ||&lt;br /&gt;
|-&lt;br /&gt;
|title||other||scale_id&lt;br /&gt;
|-&lt;br /&gt;
|question||mandatory||same_default&lt;br /&gt;
|-&lt;br /&gt;
|preg||question_order||relevance&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==list_questions==&lt;br /&gt;
&lt;br /&gt;
RPC Routine to return the ids and info of questions of a survey/group.&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
&lt;br /&gt;
sSessionKey (string) - Auth credentials&lt;br /&gt;
&lt;br /&gt;
iSurveyID (int) - Id of the survey to get questions of&lt;br /&gt;
&lt;br /&gt;
iGroupID  (int) - Id of the group to get questions of&lt;br /&gt;
&lt;br /&gt;
sLanguage (string)  -  Optional parameter language for multilingual questions&lt;br /&gt;
&lt;br /&gt;
Returns:&lt;br /&gt;
*On success: (array) The list of the questions&lt;br /&gt;
*On failure: (array) Failure status&lt;br /&gt;
**Invalid session key&lt;br /&gt;
**No permission&lt;br /&gt;
**Invalid questionid&lt;br /&gt;
**Invalid language&lt;br /&gt;
**Invalid survey ID&lt;br /&gt;
**Missmatch in surveyid and groupid&lt;br /&gt;
**No questions found&lt;br /&gt;
&lt;br /&gt;
==activate_tokens==&lt;br /&gt;
&lt;br /&gt;
Activate tokens&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
&lt;br /&gt;
session key (string) The session key&lt;br /&gt;
&lt;br /&gt;
surveyid (string) The survey ID&lt;br /&gt;
&lt;br /&gt;
additional_attributes (array of integers) Any additional attribute fields to create. Just give the attribute IDs&lt;br /&gt;
&lt;br /&gt;
Returns:&lt;br /&gt;
*On success: (array) status OK&lt;br /&gt;
*On failure: (array) Any other status&lt;br /&gt;
&lt;br /&gt;
==add_participants==&lt;br /&gt;
&lt;br /&gt;
Using this function you can add new entries to your token table. You can also set if for these new entries a token key is automatically created. Please note that this function does not check for duplicate content in any of the fields, except for token keys created by the function itself.&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*sessionkey (string) - The session key&lt;br /&gt;
*surveyID (string) - The survey id&lt;br /&gt;
*participantData (array) -  2-dimensional array/structure containing your participants data&lt;br /&gt;
*createTokenKey (boolean) - Set this to true if you want a token key create automatically for each entry - if your participant data included a [token] field it will be overwritten&lt;br /&gt;
&lt;br /&gt;
Returns:&lt;br /&gt;
*On success:  participant data (struct) -  structure containing your participants data plus the token ID and (if applicable) the new token&lt;br /&gt;
*On failure: (array) Failure status&lt;br /&gt;
**Invalid session key&lt;br /&gt;
**No permission&lt;br /&gt;
**Invalid survey ID&lt;br /&gt;
&lt;br /&gt;
JSON-RPC example:&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;
{&amp;quot;id&amp;quot;:&amp;quot;1&amp;quot;,&amp;quot;method&amp;quot;:&amp;quot;add_participants&amp;quot;,&amp;quot;params&amp;quot;:{&amp;quot;sessionkey&amp;quot;:&amp;quot;73e8rx864rnxmk64gp67bah44u2igivm&amp;quot;,&amp;quot;surveyID&amp;quot;:&amp;quot;668138&amp;quot;,&amp;quot;participantData&amp;quot;:[{&amp;quot;email&amp;quot;:&amp;quot;me@example.com&amp;quot;,&amp;quot;lastname&amp;quot;:&amp;quot;Bond&amp;quot;,&amp;quot;firstname&amp;quot;:&amp;quot;James&amp;quot;}]}}&lt;br /&gt;
&lt;br /&gt;
Response:&lt;br /&gt;
&lt;br /&gt;
{&amp;quot;id&amp;quot;:&amp;quot;1&amp;quot;,&amp;quot;result&amp;quot;:[{&amp;quot;email&amp;quot;:&amp;quot;me@example.com&amp;quot;,&amp;quot;lastname&amp;quot;:&amp;quot;Bond&amp;quot;,&amp;quot;firstname&amp;quot;:&amp;quot;James&amp;quot;,&amp;quot;tid&amp;quot;:&amp;quot;1&amp;quot;,&amp;quot;token&amp;quot;:&amp;quot;auc82gar58dpcg6&amp;quot;}],&amp;quot;error&amp;quot;:null}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==delete_participants==&lt;br /&gt;
&lt;br /&gt;
RPC Routine to delete multiple participants of a Survey&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
&lt;br /&gt;
sSessionKey (string) - Auth credentials&lt;br /&gt;
&lt;br /&gt;
iSurveyID (int) - Id of the survey to get questions of&lt;br /&gt;
&lt;br /&gt;
aTokenIDs  (array) - IId of the tokens/participants to delete&lt;br /&gt;
&lt;br /&gt;
Returns:&lt;br /&gt;
*On success: (array) Array of deletion status for each participant&lt;br /&gt;
*On failure: (array) Failure status&lt;br /&gt;
**Invalid session key&lt;br /&gt;
**No permission&lt;br /&gt;
**Invalid survey ID&lt;br /&gt;
**No token table&lt;br /&gt;
&lt;br /&gt;
==get_participant_properties==&lt;br /&gt;
&lt;br /&gt;
RPC Routine to return settings of a token/participant of a survey&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
&lt;br /&gt;
sSessionKey (string) -  Auth credentials&lt;br /&gt;
&lt;br /&gt;
iSurveyID  (int) - Id of the Survey to get token properties&lt;br /&gt;
&lt;br /&gt;
iTokenID (int) - Id of the participant to check&lt;br /&gt;
&lt;br /&gt;
aTokenProperties (array) - The properties to get&lt;br /&gt;
&lt;br /&gt;
Returns:&lt;br /&gt;
*On success: (array) Array of requested values&lt;br /&gt;
*On failure: (array) Failure status&lt;br /&gt;
**Invalid session key&lt;br /&gt;
**No permission&lt;br /&gt;
**Invalid survey ID&lt;br /&gt;
**No token table&lt;br /&gt;
**Invalid tokenid&lt;br /&gt;
**No valid Data&lt;br /&gt;
&lt;br /&gt;
Available Parameters:&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|   ||   ||&lt;br /&gt;
|-&lt;br /&gt;
|tid||   token||   completed&lt;br /&gt;
|-&lt;br /&gt;
| participant_id ||   language||   usesleft&lt;br /&gt;
|-&lt;br /&gt;
|firstname||   blacklisted||   validfrom&lt;br /&gt;
|-&lt;br /&gt;
|   lastname||   sent||   validuntil&lt;br /&gt;
|-&lt;br /&gt;
|email||   remindersent||   mpid&lt;br /&gt;
|-&lt;br /&gt;
|emailstatus||   remindercount||   &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==set_participant_properties==&lt;br /&gt;
&lt;br /&gt;
RPC Routine to set properties of a survey participant/token&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
&lt;br /&gt;
sSessionKey (string) -  Auth credentials&lt;br /&gt;
&lt;br /&gt;
iSurveyID  (int) - Id of the Survey to set token properties&lt;br /&gt;
&lt;br /&gt;
iTokenID (int) - Id of the participant to alter&lt;br /&gt;
&lt;br /&gt;
aTokenData (array) - Key - value pair of the properties to set&lt;br /&gt;
&lt;br /&gt;
Returns:&lt;br /&gt;
*On success: (array) Array of results of changing properties&lt;br /&gt;
*On failure: (array) Failure status&lt;br /&gt;
**Invalid session key&lt;br /&gt;
**No permission&lt;br /&gt;
**Invalid survey ID&lt;br /&gt;
**No token table&lt;br /&gt;
**Invalid tokenid&lt;br /&gt;
**No valid Data&lt;br /&gt;
&lt;br /&gt;
Available Parameters:&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|   ||   ||&lt;br /&gt;
|-&lt;br /&gt;
|||   token||   completed&lt;br /&gt;
|-&lt;br /&gt;
| participant_id ||   language||   usesleft&lt;br /&gt;
|-&lt;br /&gt;
|firstname||   blacklisted||   validfrom&lt;br /&gt;
|-&lt;br /&gt;
|   lastname||   sent||   validuntil&lt;br /&gt;
|-&lt;br /&gt;
|email||   remindersent||   mpid&lt;br /&gt;
|-&lt;br /&gt;
|emailstatus||   remindercount||   &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==list_participants==&lt;br /&gt;
&lt;br /&gt;
RPC routine to return the IDs and info of token/participants of a survey.&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
&lt;br /&gt;
   sSessionKey (string) -  Auth credentials&lt;br /&gt;
   iSurveyID  (int) - Id of the survey to list participants&lt;br /&gt;
   iStart (int) - Start id of the token list&lt;br /&gt;
   iLimit (int) - Number of participants to return&lt;br /&gt;
   bUnused (bool) - If you want unused tokensm, set true&lt;br /&gt;
   aAttributes(bool|array) An array of extended attributes that can be requested, besides the default ones (default value to false)&lt;br /&gt;
&lt;br /&gt;
Returns:&lt;br /&gt;
*On success: (array) Array of Participants info&lt;br /&gt;
*On failure: (array) Failure status&lt;br /&gt;
**Invalid session key&lt;br /&gt;
**No permission&lt;br /&gt;
**Invalid survey ID&lt;br /&gt;
**No token table&lt;br /&gt;
**No Tokens found&lt;br /&gt;
&lt;br /&gt;
==activate_tokens==&lt;br /&gt;
&lt;br /&gt;
RPC routine to to initialise the survey&#039;s collection of tokens where new participant tokens may be later added&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
&lt;br /&gt;
sSessionKey (string) -  Auth credentials&lt;br /&gt;
&lt;br /&gt;
iSurveyID  (int) - Id of the survey to list participants&lt;br /&gt;
&lt;br /&gt;
aAttributeFields (array) - An array of integer describing any additional attribute fields&lt;br /&gt;
&lt;br /&gt;
Returns:&lt;br /&gt;
*On success: (array) Status OK&lt;br /&gt;
*On failure: (array) Failure status&lt;br /&gt;
**Invalid session key&lt;br /&gt;
**No permission&lt;br /&gt;
**Invalid survey ID&lt;br /&gt;
**Token table could not be created&lt;br /&gt;
&lt;br /&gt;
==invite_participants==&lt;br /&gt;
&lt;br /&gt;
RPC Routine to invite participants in a survey&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
&lt;br /&gt;
sSessionKey (string) -  Auth credentials&lt;br /&gt;
&lt;br /&gt;
iSurveyID  (int) - Id of the survey to send invitation to participants&lt;br /&gt;
&lt;br /&gt;
Returns:&lt;br /&gt;
*On success: (array)  Array of result of each email send action and count of invitations left to send&lt;br /&gt;
*On failure: (array) Failure status&lt;br /&gt;
**Invalid session key&lt;br /&gt;
**No permission&lt;br /&gt;
**Invalid survey ID&lt;br /&gt;
**No token table&lt;br /&gt;
**No candidate tokens&lt;br /&gt;
&lt;br /&gt;
==remind_participants==&lt;br /&gt;
&lt;br /&gt;
RPC Routine to send reminder for participants in a survey&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
&lt;br /&gt;
sSessionKey (string) -  Auth credentials&lt;br /&gt;
&lt;br /&gt;
iSurveyID  (int) - Id of the survey to send invitation to participants&lt;br /&gt;
&lt;br /&gt;
iMinDaysBetween (int) - Optional parameter days from last reminder&lt;br /&gt;
&lt;br /&gt;
iMaxReminders (int) - Optional parameter Maximum reminders count&lt;br /&gt;
&lt;br /&gt;
Returns:&lt;br /&gt;
*On success: (array)  Array of result of each email send action and count of invitations left to send&lt;br /&gt;
*On failure: (array) Failure status&lt;br /&gt;
**Invalid session key&lt;br /&gt;
**No permission&lt;br /&gt;
**Invalid survey ID&lt;br /&gt;
**No token table&lt;br /&gt;
**No candidate tokens&lt;br /&gt;
&lt;br /&gt;
==add_response==&lt;br /&gt;
&lt;br /&gt;
Using this function you can add new responses to your survey response table.&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
*sSessionKey (string) - The session key&lt;br /&gt;
*iSurveyID (integer) - The survey id&lt;br /&gt;
*aResponseData (array) -  array/structure containing your response data&lt;br /&gt;
&lt;br /&gt;
Returns:&lt;br /&gt;
*On success: response_id (integer) -  Returns the id of the inserted survey response&lt;br /&gt;
*On failure: (array) with error description&lt;br /&gt;
&lt;br /&gt;
==export_responses==&lt;br /&gt;
&lt;br /&gt;
Export response data to pdf,csv,xls,doc&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
&lt;br /&gt;
sSessionKey (string) - Auth credentials&lt;br /&gt;
&lt;br /&gt;
SurveyID (int) - Id of the Survey&lt;br /&gt;
&lt;br /&gt;
DocumentType (string) - pdf,csv,xls,doc&lt;br /&gt;
&lt;br /&gt;
sLanguageCode (string) - Optional The language to be used - if not given then the base language will be used&lt;br /&gt;
&lt;br /&gt;
CompletionStatus (string) - Optional &#039;complete&#039;,&#039;incomplete&#039; or &#039;all&#039; selection of responses - defaults to complete&lt;br /&gt;
&lt;br /&gt;
HeadingType (string) - &#039;code&#039;,&#039;full&#039; or &#039;abbreviated&#039;. type of question heading. Optional defaults to &#039;code&#039;&lt;br /&gt;
&lt;br /&gt;
ResponseType (string) - &#039;short&#039; or &#039;long&#039; response type.Optional defaults to &#039;short&#039;&lt;br /&gt;
&lt;br /&gt;
FromResponse (int) - Optional start number of response&lt;br /&gt;
&lt;br /&gt;
ToResponse (int) - Optional end number of responses&lt;br /&gt;
&lt;br /&gt;
Return:&lt;br /&gt;
&lt;br /&gt;
On success: Requested file as base 64-encoded string.&lt;br /&gt;
&lt;br /&gt;
On failure: Array with error information&lt;br /&gt;
&lt;br /&gt;
Note: If you have huge response sets try only to request a certain number of records at a time otherwise the server may run out of memory.&lt;br /&gt;
&lt;br /&gt;
==export_responses_by_token==&lt;br /&gt;
&lt;br /&gt;
Export responses data of specific token to pdf,csv,xls,doc&lt;br /&gt;
&lt;br /&gt;
Parameters:&lt;br /&gt;
&lt;br /&gt;
sSessionKey (string) - Auth credentials&lt;br /&gt;
&lt;br /&gt;
SurveyID (int) - Id of the Survey&lt;br /&gt;
&lt;br /&gt;
DocumentType (string) - pdf,csv,xls,doc&lt;br /&gt;
&lt;br /&gt;
sToken (string) - Token string of a candidate&lt;br /&gt;
&lt;br /&gt;
sLanguageCode (string) - Optional The language to be used - if not given then the base language will be used&lt;br /&gt;
&lt;br /&gt;
CompletionStatus (string) - Optional &#039;complete&#039;,&#039;incomplete&#039; or &#039;all&#039; selection of responses - defaults to complete&lt;br /&gt;
&lt;br /&gt;
HeadingType (string) - &#039;code&#039;,&#039;full&#039; or &#039;abbreviated&#039;. type of question heading. Optional defaults to &#039;code&#039;&lt;br /&gt;
&lt;br /&gt;
ResponseType (string) - &#039;short&#039; or &#039;long&#039; response type.Optional defaults to &#039;short&#039;&lt;br /&gt;
&lt;br /&gt;
aFields (array) - Optional Selected fields&lt;br /&gt;
&lt;br /&gt;
Return:&lt;br /&gt;
&lt;br /&gt;
On success: Requested file as base 64-encoded string.&lt;br /&gt;
&lt;br /&gt;
On failure: Array with error information&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Testing=&lt;br /&gt;
&lt;br /&gt;
To test you will have to activate JSON-RPC in global settings. To run a simple self-test go to&lt;br /&gt;
&lt;br /&gt;
http://path_to_your_limesurvey_installation/index.php/admin/remotecontrol/test . This will import the example survey, do various things with it and delete it afterwards.&lt;br /&gt;
&lt;br /&gt;
The test assumes that you still are using the standard user &#039;admin&#039; with password &#039;password&#039;.&lt;br /&gt;
&lt;br /&gt;
The client function for this test can be found in /application/controller/admin/remotecontrol.php and the particular function is called test().&lt;br /&gt;
&lt;br /&gt;
=Ruby Example=&lt;br /&gt;
&lt;br /&gt;
==Load Requirements and Declare Values==&lt;br /&gt;
You will first need to require the dependencies needed to establish communication with the API. Also, note that there is a username and password field that requires to be stored in plain text. I have a separate API User within my LimeSurvey to handle these calls.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ruby&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
#!/usr/bin/env ruby&lt;br /&gt;
&lt;br /&gt;
require &#039;net/https&#039;&lt;br /&gt;
require &#039;uri&#039;&lt;br /&gt;
require &#039;json&#039;&lt;br /&gt;
&lt;br /&gt;
username = &amp;quot;api_user&amp;quot;&lt;br /&gt;
password = &amp;quot;api_user&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Module==&lt;br /&gt;
&lt;br /&gt;
The below code is used to define the module LimeSurvey. Within this module is an API class. We will use this to create an instance of this module and then call on the API call wherever needed.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ruby&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
module LimeSurvey&lt;br /&gt;
  class API&lt;br /&gt;
    def initialize(service_url)&lt;br /&gt;
      @uri = URI.parse(service_url)&lt;br /&gt;
    end&lt;br /&gt;
   &lt;br /&gt;
    def method_missing(name, *args)&lt;br /&gt;
      post_body = { &#039;method&#039; =&amp;gt; name, &#039;params&#039; =&amp;gt; args, &#039;id&#039; =&amp;gt; &#039;jsonrpc&#039; }.to_json&lt;br /&gt;
      resp = JSON.parse( http_post_request(post_body) )&lt;br /&gt;
      raise JSONRPCError, resp[&#039;error&#039;] if resp[&#039;error&#039;]&lt;br /&gt;
      resp[&#039;result&#039;]&lt;br /&gt;
    end&lt;br /&gt;
   &lt;br /&gt;
    def http_post_request(post_body)&lt;br /&gt;
      http    = Net::HTTP.new(@uri.host, @uri.port)&lt;br /&gt;
      request = Net::HTTP::Post.new(@uri.request_uri)&lt;br /&gt;
      request.content_type = &#039;application/json&#039;&lt;br /&gt;
      request.body = post_body&lt;br /&gt;
      http.request(request).body&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
&lt;br /&gt;
  class JSONRPCError &amp;lt; RuntimeError; end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==API Call==&lt;br /&gt;
This code is used to create the instance of the LimeSurvey::API module and class. You will want to change the URL to that of your RemoteControl2 URL.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ruby&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
survey = LimeSurvey::API.new(&#039;http://localhost/limesurvey/index.php?r=admin/remotecontrol&#039;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Examples==&lt;br /&gt;
This example takes the above code and puts it into play. I create a new session with the RemoteControl2 API and store the session in the variable session_key. You will want to change the ID numbers to the appropriate Survey ID in the examples.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ruby&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
system(&amp;quot;cls&amp;quot;)&lt;br /&gt;
session_key = survey.get_session_key(username,password)&lt;br /&gt;
puts &amp;quot;Session Key: #{session_key}&amp;quot;&lt;br /&gt;
puts &amp;quot;\n&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
response = survey.get_survey_properties(session_key, &amp;quot;863224&amp;quot;, [&amp;quot;owner_id&amp;quot;])&lt;br /&gt;
puts &amp;quot;Properties:  #{response}&amp;quot;&lt;br /&gt;
puts &amp;quot;\n&amp;quot;&lt;br /&gt;
&lt;br /&gt;
response = survey.list_surveys(sSessionKey: session_key, sUser: &amp;quot;dkimura&amp;quot;)&lt;br /&gt;
puts &amp;quot;Survey List:  #{response}&amp;quot;&lt;br /&gt;
puts &amp;quot;\n&amp;quot;&lt;br /&gt;
&lt;br /&gt;
response = survey.add_participants(&lt;br /&gt;
    session_key, &lt;br /&gt;
    &amp;quot;863224&amp;quot;,&lt;br /&gt;
    [email:&amp;quot;james.bond@example.com&amp;quot;,lastname:&amp;quot;Bond&amp;quot;,firstname:&amp;quot;James&amp;quot;]&lt;br /&gt;
  )&lt;br /&gt;
puts &amp;quot;Add Participant:  #{response}&amp;quot;&lt;br /&gt;
puts &amp;quot;\n&amp;quot;&lt;br /&gt;
&lt;br /&gt;
response = survey.invite_participants(&lt;br /&gt;
    session_key, &lt;br /&gt;
    &amp;quot;863224&amp;quot;&lt;br /&gt;
  )&lt;br /&gt;
puts &amp;quot;Invite Participant:  #{response}&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Example Return==&lt;br /&gt;
&lt;br /&gt;
From the above example, here is the return that I receive. Some of the items are returned as a hash and some items returned as an array of hashes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;ruby&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;&lt;br /&gt;
Session Key: piadscbc94vyanxwkdy8f3xii4av2b2w&lt;br /&gt;
&lt;br /&gt;
Properties:  {&amp;quot;owner_id&amp;quot;=&amp;gt;&amp;quot;1&amp;quot;}&lt;br /&gt;
&lt;br /&gt;
Survey List:  [{&amp;quot;sid&amp;quot;=&amp;gt;&amp;quot;863224&amp;quot;, &amp;quot;surveyls_title&amp;quot;=&amp;gt;&amp;quot;Statement of Work v0.12&amp;quot;, &amp;quot;startdate&amp;quot;=&amp;gt;nil, &amp;quot;expires&amp;quot;=&amp;gt;nil, &amp;quot;active&amp;quot;=&amp;gt;&amp;quot;Y&amp;quot;}]&lt;br /&gt;
&lt;br /&gt;
Add Participant:  [{&amp;quot;email&amp;quot;=&amp;gt;&amp;quot;james.bond@example.com&amp;quot;, &amp;quot;lastname&amp;quot;=&amp;gt;&amp;quot;Bond&amp;quot;, &amp;quot;firstname&amp;quot;=&amp;gt;&amp;quot;James&amp;quot;, &amp;quot;tid&amp;quot;=&amp;gt;&amp;quot;7&amp;quot;, &amp;quot;token&amp;quot;=&amp;gt;&amp;quot;pt5ztzxndibkz4j&amp;quot;}]&lt;br /&gt;
&lt;br /&gt;
Invite Participant:  {&amp;quot;7&amp;quot;=&amp;gt;{&amp;quot;name&amp;quot;=&amp;gt;&amp;quot;James Bond&amp;quot;, &amp;quot;email&amp;quot;=&amp;gt;&amp;quot;james.bond@example.com&amp;quot;, &amp;quot;status&amp;quot;=&amp;gt;&amp;quot;OK&amp;quot;}, &amp;quot;status&amp;quot;=&amp;gt;&amp;quot;0 left to send&amp;quot;}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&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 based on the tiny jsonRPCClient from [http://jsonrpcphp.org/ | jsonrpcphp.org]&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;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
require_once &#039;jsonRPCClient.php&#039;;&lt;br /&gt;
&lt;br /&gt;
define( &#039;LS_BASEURL&#039;, &#039;http://localhost/limesurvey/&#039;);  // adjust this one to your actual LimeSurvey URL&lt;br /&gt;
&lt;br /&gt;
define( &#039;LS_USER&#039;, &#039;rpcuser&#039; );&lt;br /&gt;
&lt;br /&gt;
define( &#039;LS_PASSWORD&#039;, &#039;mypassword&#039; );&lt;br /&gt;
&lt;br /&gt;
// the survey to process&lt;br /&gt;
&lt;br /&gt;
$survey_id=374699;&lt;br /&gt;
&lt;br /&gt;
// instanciate a new client&lt;br /&gt;
&lt;br /&gt;
$myJSONRPCClient = new jsonRPCClient( LS_BASEURL.&#039;/admin/remotecontrol&#039; );&lt;br /&gt;
&lt;br /&gt;
// receive session key&lt;br /&gt;
&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;
&lt;br /&gt;
$groups = $myJSONRPCClient-&amp;gt;list_groups( $sessionKey, $survey_id );&lt;br /&gt;
&lt;br /&gt;
print_r($groups, null );&lt;br /&gt;
&lt;br /&gt;
// release the session key&lt;br /&gt;
&lt;br /&gt;
$myJSONRPCClient-&amp;gt;release_session_key( $sessionKey );&lt;br /&gt;
&lt;br /&gt;
?&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=JAVA example=&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=65&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;username&amp;quot;:&amp;quot;admin&amp;quot;,&amp;quot;password&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;br /&gt;
&lt;br /&gt;
=Changes=&lt;br /&gt;
&lt;br /&gt;
2.0a Only three functions are supported right now: getSessionKey, releaseSessionKey, deleteSurvey&lt;br /&gt;
&lt;br /&gt;
2.0b Added function add_participants&lt;br /&gt;
&lt;br /&gt;
2.0RC5 Added import_survey, activate_survey, activate_tokens&lt;br /&gt;
&lt;br /&gt;
2.0 (build 121030) Added subquestions, attributes, attributes_lang and answeroptions properties for get_question_properties&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
for further changes check the Limesurvey release notes, thanks!&lt;br /&gt;
&lt;br /&gt;
[[Category:Development]]&lt;/div&gt;</summary>
		<author><name>Mdekker</name></author>
	</entry>
	<entry>
		<id>https://www.limesurvey.org/manual/index.php?title=Authentication_plugins&amp;diff=38364</id>
		<title>Authentication plugins</title>
		<link rel="alternate" type="text/html" href="https://www.limesurvey.org/manual/index.php?title=Authentication_plugins&amp;diff=38364"/>
		<updated>2013-06-11T14:42:37Z</updated>

		<summary type="html">&lt;p&gt;Mdekker: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;An authentication plugin has some additional requirements over a regular plugin. Here we list the requirements.&lt;br /&gt;
&lt;br /&gt;
To make creating your own authentication plugin easier, you should extend the abstract [https://github.com/LimeSurvey/LimeSurvey/blob/2.05/application/libraries/PluginManager/AuthPluginBase.php AuthPluginBase] class.&lt;br /&gt;
&lt;br /&gt;
To get an idea of the possibilities, check out the three core authentication plugins (check their pages for more information about configuration options):&lt;br /&gt;
* [https://github.com/LimeSurvey/LimeSurvey/blob/2.05/application/core/plugins/Authdb/Authdb.php Authdb] Database authentication - this is the default method for all new LimeSurvey installations&lt;br /&gt;
* [https://github.com/LimeSurvey/LimeSurvey/blob/2.05/application/core/plugins/Authwebserver/Authwebserver.php Authwebserver] Webserver authentication - This one skips the login form, and provides methods for user creation&lt;br /&gt;
* [https://github.com/LimeSurvey/LimeSurvey/blob/2.05/application/core/plugins/AuthLDAP/AuthLDAP.php AuthLDAP] LDAP authentication - Adds a custom error message and relies on a user being present in the LimeSurvey database.&lt;br /&gt;
&lt;br /&gt;
There are 4 events you can subscribe to:&lt;br /&gt;
&lt;br /&gt;
== beforeLogin ==&lt;br /&gt;
This is called first, and can possibly disable the loginform, for example when webserver authentication is used and we trust on that. To do this, use &#039;&#039;$this-&amp;gt;setAuthPlugin()&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== newLoginForm ==&lt;br /&gt;
Here you can add your own elements to the form. You should add your username/password elements, but could also add a domain selector or anything else you need. This will only be shown when the selected authentication method was chosen on the selector that is added when more then one plugin is present. When your authentication plugin does not need a form, and can not be selected as an option (like webserver authentication) you should not add a form element here.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$this-&amp;gt;getEvent()                  // Get the current event&lt;br /&gt;
     -&amp;gt;getContent($this)           // Get the content for this plugin&lt;br /&gt;
     -&amp;gt;addContent(CHtml::tag(      // And add some content to it&lt;br /&gt;
         &#039;li&#039;, &lt;br /&gt;
         array(), &lt;br /&gt;
         &amp;quot;&amp;lt;label for=&#039;user&#039;&amp;gt;&amp;quot;  . gT(&amp;quot;Username&amp;quot;) . &amp;quot;&amp;lt;/label&amp;gt;&amp;lt;input name=&#039;user&#039; id=&#039;user&#039; type=&#039;text&#039; size=&#039;40&#039; maxlength=&#039;40&#039; value=&#039;&#039; /&amp;gt;&amp;quot;))&lt;br /&gt;
     -&amp;gt;addContent(CHtml::tag(&lt;br /&gt;
         &#039;li&#039;, &lt;br /&gt;
         array(), &lt;br /&gt;
         &amp;quot;&amp;lt;label for=&#039;password&#039;&amp;gt;&amp;quot;  . gT(&amp;quot;Password&amp;quot;) . &amp;quot;&amp;lt;/label&amp;gt;&amp;lt;input name=&#039;password&#039; id=&#039;password&#039; type=&#039;password&#039; size=&#039;40&#039; maxlength=&#039;40&#039; value=&#039;&#039; /&amp;gt;&amp;quot;));&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== afterLoginFormSubmit ==&lt;br /&gt;
When the form for this plugin was submitted, this event is called. Here you can handle setting the values to the plugin. This event is also called when there was no form submitted and form display was canceled in the beforeLogin event.&lt;br /&gt;
&lt;br /&gt;
== newUserSession ==&lt;br /&gt;
This is where the real authentication takes place. You should use $this-&amp;gt;setAuthSuccess($oUser) for a successful attempt and provide a User object. If you fail to do so it will result in an authentication failure. If you need to provide a message about why the authentication failed, you can do so by using $this-&amp;gt;setAuthFailure($code, $message) where code is any code other than 0. The code is not used at this moment. The message should be a message in English, localised using the available tools in the plugin api. See the general plugin documenation for more information about that topic.&lt;br /&gt;
&lt;br /&gt;
[[Category:Plugins]]&lt;/div&gt;</summary>
		<author><name>Mdekker</name></author>
	</entry>
	<entry>
		<id>https://www.limesurvey.org/manual/index.php?title=Authentication_plugins&amp;diff=38363</id>
		<title>Authentication plugins</title>
		<link rel="alternate" type="text/html" href="https://www.limesurvey.org/manual/index.php?title=Authentication_plugins&amp;diff=38363"/>
		<updated>2013-06-11T14:38:33Z</updated>

		<summary type="html">&lt;p&gt;Mdekker: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;An authentication plugin has some additional requirements over a regular plugin. Here we list the requirements.&lt;br /&gt;
&lt;br /&gt;
To make creating your own authentication plugin easier, you should extend the abstract [https://github.com/LimeSurvey/LimeSurvey/blob/2.05/application/libraries/PluginManager/AuthPluginBase.php AuthPluginBase] class.&lt;br /&gt;
&lt;br /&gt;
To get an idea of the possibilities, check out the three core authentication plugins (check their pages for more information about configuration options):&lt;br /&gt;
[https://github.com/LimeSurvey/LimeSurvey/blob/2.05/application/core/plugins/Authdb/Authdb.php Authdb] Database authentication - this is the default method for all new LimeSurvey installations&lt;br /&gt;
[https://github.com/LimeSurvey/LimeSurvey/blob/2.05/application/core/plugins/Authwebserver/Authwebserver.php Authwebserver] Webserver authentication&lt;br /&gt;
[https://github.com/LimeSurvey/LimeSurvey/blob/2.05/application/core/plugins/AuthLDAP/AuthLDAP.php AuthLDAP] LDAP authentication&lt;br /&gt;
&lt;br /&gt;
There are 4 events you can subscribe to:&lt;br /&gt;
&lt;br /&gt;
== beforeLogin ==&lt;br /&gt;
This is called first, and can possibly disable the loginform, for example when webserver authentication is used and we trust on that. To do this, use &#039;&#039;$this-&amp;gt;setAuthPlugin()&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== newLoginForm ==&lt;br /&gt;
Here you can add your own elements to the form. You should add your username/password elements, but could also add a domain selector or anything else you need. This will only be shown when the selected authentication method was chosen on the selector that is added when more then one plugin is present. When your authentication plugin does not need a form, and can not be selected as an option (like webserver authentication) you should not add a form element here.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$this-&amp;gt;getEvent()                  // Get the current event&lt;br /&gt;
     -&amp;gt;getContent($this)           // Get the content for this plugin&lt;br /&gt;
     -&amp;gt;addContent(CHtml::tag(      // And add some content to it&lt;br /&gt;
         &#039;li&#039;, &lt;br /&gt;
         array(), &lt;br /&gt;
         &amp;quot;&amp;lt;label for=&#039;user&#039;&amp;gt;&amp;quot;  . gT(&amp;quot;Username&amp;quot;) . &amp;quot;&amp;lt;/label&amp;gt;&amp;lt;input name=&#039;user&#039; id=&#039;user&#039; type=&#039;text&#039; size=&#039;40&#039; maxlength=&#039;40&#039; value=&#039;&#039; /&amp;gt;&amp;quot;))&lt;br /&gt;
     -&amp;gt;addContent(CHtml::tag(&lt;br /&gt;
         &#039;li&#039;, &lt;br /&gt;
         array(), &lt;br /&gt;
         &amp;quot;&amp;lt;label for=&#039;password&#039;&amp;gt;&amp;quot;  . gT(&amp;quot;Password&amp;quot;) . &amp;quot;&amp;lt;/label&amp;gt;&amp;lt;input name=&#039;password&#039; id=&#039;password&#039; type=&#039;password&#039; size=&#039;40&#039; maxlength=&#039;40&#039; value=&#039;&#039; /&amp;gt;&amp;quot;));&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== afterLoginFormSubmit ==&lt;br /&gt;
When the form for this plugin was submitted, this event is called. Here you can handle setting the values to the plugin. This event is also called when there was no form submitted and form display was canceled in the beforeLogin event.&lt;br /&gt;
&lt;br /&gt;
== newUserSession ==&lt;br /&gt;
This is where the real authentication takes place. You should use $this-&amp;gt;setAuthSuccess($oUser) for a successful attempt and provide a User object. If you fail to do so it will result in an authentication failure. If you need to provide a message about why the authentication failed, you can do so by using $this-&amp;gt;setAuthFailure($code, $message) where code is any code other than 0. The code is not used at this moment. The message should be a message in English, localised using the available tools in the plugin api. See the general plugin documenation for more information about that topic.&lt;br /&gt;
&lt;br /&gt;
[[Category:Plugins]]&lt;/div&gt;</summary>
		<author><name>Mdekker</name></author>
	</entry>
	<entry>
		<id>https://www.limesurvey.org/manual/index.php?title=Authentication_plugins&amp;diff=38362</id>
		<title>Authentication plugins</title>
		<link rel="alternate" type="text/html" href="https://www.limesurvey.org/manual/index.php?title=Authentication_plugins&amp;diff=38362"/>
		<updated>2013-06-11T14:34:38Z</updated>

		<summary type="html">&lt;p&gt;Mdekker: /* newUserSession */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;An authentication plugin has some additional requirements over a regular plugin. Here we list the requirements.&lt;br /&gt;
&lt;br /&gt;
To make creating your own authentication plugin easier, you should extend the abstract [https://github.com/LimeSurvey/LimeSurvey/blob/2.05/application/libraries/PluginManager/AuthPluginBase.php AuthPluginBase] class.&lt;br /&gt;
&lt;br /&gt;
There are 4 events you can subscribe to:&lt;br /&gt;
&lt;br /&gt;
== beforeLogin ==&lt;br /&gt;
This is called first, and can possibly disable the loginform, for example when webserver authentication is used and we trust on that. To do this, use &#039;&#039;$this-&amp;gt;setAuthPlugin()&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== newLoginForm ==&lt;br /&gt;
Here you can add your own elements to the form. You should add your username/password elements, but could also add a domain selector or anything else you need. This will only be shown when the selected authentication method was chosen on the selector that is added when more then one plugin is present. When your authentication plugin does not need a form, and can not be selected as an option (like webserver authentication) you should not add a form element here.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$this-&amp;gt;getEvent()                  // Get the current event&lt;br /&gt;
     -&amp;gt;getContent($this)           // Get the content for this plugin&lt;br /&gt;
     -&amp;gt;addContent(CHtml::tag(      // And add some content to it&lt;br /&gt;
         &#039;li&#039;, &lt;br /&gt;
         array(), &lt;br /&gt;
         &amp;quot;&amp;lt;label for=&#039;user&#039;&amp;gt;&amp;quot;  . gT(&amp;quot;Username&amp;quot;) . &amp;quot;&amp;lt;/label&amp;gt;&amp;lt;input name=&#039;user&#039; id=&#039;user&#039; type=&#039;text&#039; size=&#039;40&#039; maxlength=&#039;40&#039; value=&#039;&#039; /&amp;gt;&amp;quot;))&lt;br /&gt;
     -&amp;gt;addContent(CHtml::tag(&lt;br /&gt;
         &#039;li&#039;, &lt;br /&gt;
         array(), &lt;br /&gt;
         &amp;quot;&amp;lt;label for=&#039;password&#039;&amp;gt;&amp;quot;  . gT(&amp;quot;Password&amp;quot;) . &amp;quot;&amp;lt;/label&amp;gt;&amp;lt;input name=&#039;password&#039; id=&#039;password&#039; type=&#039;password&#039; size=&#039;40&#039; maxlength=&#039;40&#039; value=&#039;&#039; /&amp;gt;&amp;quot;));&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== afterLoginFormSubmit ==&lt;br /&gt;
When the form for this plugin was submitted, this event is called. Here you can handle setting the values to the plugin. This event is also called when there was no form submitted and form display was canceled in the beforeLogin event.&lt;br /&gt;
&lt;br /&gt;
== newUserSession ==&lt;br /&gt;
This is where the real authentication takes place. You should use $this-&amp;gt;setAuthSuccess($oUser) for a successful attempt and provide a User object. If you fail to do so it will result in an authentication failure. If you need to provide a message about why the authentication failed, you can do so by using $this-&amp;gt;setAuthFailure($code, $message) where code is any code other than 0. The code is not used at this moment. The message should be a message in English, localised using the available tools in the plugin api. See the general plugin documenation for more information about that topic.&lt;br /&gt;
&lt;br /&gt;
[[Category:Plugins]]&lt;/div&gt;</summary>
		<author><name>Mdekker</name></author>
	</entry>
	<entry>
		<id>https://www.limesurvey.org/manual/index.php?title=Authentication_plugins&amp;diff=38361</id>
		<title>Authentication plugins</title>
		<link rel="alternate" type="text/html" href="https://www.limesurvey.org/manual/index.php?title=Authentication_plugins&amp;diff=38361"/>
		<updated>2013-06-11T14:25:47Z</updated>

		<summary type="html">&lt;p&gt;Mdekker: /* afterLoginFormSubmit */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;An authentication plugin has some additional requirements over a regular plugin. Here we list the requirements.&lt;br /&gt;
&lt;br /&gt;
To make creating your own authentication plugin easier, you should extend the abstract [https://github.com/LimeSurvey/LimeSurvey/blob/2.05/application/libraries/PluginManager/AuthPluginBase.php AuthPluginBase] class.&lt;br /&gt;
&lt;br /&gt;
There are 4 events you can subscribe to:&lt;br /&gt;
&lt;br /&gt;
== beforeLogin ==&lt;br /&gt;
This is called first, and can possibly disable the loginform, for example when webserver authentication is used and we trust on that. To do this, use &#039;&#039;$this-&amp;gt;setAuthPlugin()&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== newLoginForm ==&lt;br /&gt;
Here you can add your own elements to the form. You should add your username/password elements, but could also add a domain selector or anything else you need. This will only be shown when the selected authentication method was chosen on the selector that is added when more then one plugin is present. When your authentication plugin does not need a form, and can not be selected as an option (like webserver authentication) you should not add a form element here.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$this-&amp;gt;getEvent()                  // Get the current event&lt;br /&gt;
     -&amp;gt;getContent($this)           // Get the content for this plugin&lt;br /&gt;
     -&amp;gt;addContent(CHtml::tag(      // And add some content to it&lt;br /&gt;
         &#039;li&#039;, &lt;br /&gt;
         array(), &lt;br /&gt;
         &amp;quot;&amp;lt;label for=&#039;user&#039;&amp;gt;&amp;quot;  . gT(&amp;quot;Username&amp;quot;) . &amp;quot;&amp;lt;/label&amp;gt;&amp;lt;input name=&#039;user&#039; id=&#039;user&#039; type=&#039;text&#039; size=&#039;40&#039; maxlength=&#039;40&#039; value=&#039;&#039; /&amp;gt;&amp;quot;))&lt;br /&gt;
     -&amp;gt;addContent(CHtml::tag(&lt;br /&gt;
         &#039;li&#039;, &lt;br /&gt;
         array(), &lt;br /&gt;
         &amp;quot;&amp;lt;label for=&#039;password&#039;&amp;gt;&amp;quot;  . gT(&amp;quot;Password&amp;quot;) . &amp;quot;&amp;lt;/label&amp;gt;&amp;lt;input name=&#039;password&#039; id=&#039;password&#039; type=&#039;password&#039; size=&#039;40&#039; maxlength=&#039;40&#039; value=&#039;&#039; /&amp;gt;&amp;quot;));&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== afterLoginFormSubmit ==&lt;br /&gt;
When the form for this plugin was submitted, this event is called. Here you can handle setting the values to the plugin. This event is also called when there was no form submitted and form display was canceled in the beforeLogin event.&lt;br /&gt;
&lt;br /&gt;
== newUserSession ==&lt;br /&gt;
This is where the real authentication takes place. You should use $this-&amp;gt;setAuthFailure($code, $message) for a failure and $this-&amp;gt;setAuthSuccess($oUser) for a successful attempt.&lt;br /&gt;
&lt;br /&gt;
[[Category:Plugins]]&lt;/div&gt;</summary>
		<author><name>Mdekker</name></author>
	</entry>
	<entry>
		<id>https://www.limesurvey.org/manual/index.php?title=Authentication_plugins&amp;diff=38325</id>
		<title>Authentication plugins</title>
		<link rel="alternate" type="text/html" href="https://www.limesurvey.org/manual/index.php?title=Authentication_plugins&amp;diff=38325"/>
		<updated>2013-06-11T14:18:01Z</updated>

		<summary type="html">&lt;p&gt;Mdekker: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;An authentication plugin has some additional requirements over a regular plugin. Here we list the requirements.&lt;br /&gt;
&lt;br /&gt;
To make creating your own authentication plugin easier, you should extend the abstract [https://github.com/LimeSurvey/LimeSurvey/blob/2.05/application/libraries/PluginManager/AuthPluginBase.php AuthPluginBase] class.&lt;br /&gt;
&lt;br /&gt;
There are 4 events you can subscribe to:&lt;br /&gt;
&lt;br /&gt;
== beforeLogin ==&lt;br /&gt;
This is called first, and can possibly disable the loginform, for example when webserver authentication is used and we trust on that. To do this, use &#039;&#039;$this-&amp;gt;setAuthPlugin()&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== newLoginForm ==&lt;br /&gt;
Here you can add your own elements to the form. You should add your username/password elements, but could also add a domain selector or anything else you need. This will only be shown when the selected authentication method was chosen on the selector that is added when more then one plugin is present. When your authentication plugin does not need a form, and can not be selected as an option (like webserver authentication) you should not add a form element here.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;php&amp;quot;&amp;gt;&lt;br /&gt;
$this-&amp;gt;getEvent()                  // Get the current event&lt;br /&gt;
     -&amp;gt;getContent($this)           // Get the content for this plugin&lt;br /&gt;
     -&amp;gt;addContent(CHtml::tag(      // And add some content to it&lt;br /&gt;
         &#039;li&#039;, &lt;br /&gt;
         array(), &lt;br /&gt;
         &amp;quot;&amp;lt;label for=&#039;user&#039;&amp;gt;&amp;quot;  . gT(&amp;quot;Username&amp;quot;) . &amp;quot;&amp;lt;/label&amp;gt;&amp;lt;input name=&#039;user&#039; id=&#039;user&#039; type=&#039;text&#039; size=&#039;40&#039; maxlength=&#039;40&#039; value=&#039;&#039; /&amp;gt;&amp;quot;))&lt;br /&gt;
     -&amp;gt;addContent(CHtml::tag(&lt;br /&gt;
         &#039;li&#039;, &lt;br /&gt;
         array(), &lt;br /&gt;
         &amp;quot;&amp;lt;label for=&#039;password&#039;&amp;gt;&amp;quot;  . gT(&amp;quot;Password&amp;quot;) . &amp;quot;&amp;lt;/label&amp;gt;&amp;lt;input name=&#039;password&#039; id=&#039;password&#039; type=&#039;password&#039; size=&#039;40&#039; maxlength=&#039;40&#039; value=&#039;&#039; /&amp;gt;&amp;quot;));&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== afterLoginFormSubmit ==&lt;br /&gt;
When the form for this plugin was submitted, this event is called. Here you can handle setting the values to the plugin.&lt;br /&gt;
&lt;br /&gt;
== newUserSession ==&lt;br /&gt;
This is where the real authentication takes place. You should use $this-&amp;gt;setAuthFailure($code, $message) for a failure and $this-&amp;gt;setAuthSuccess($oUser) for a successful attempt.&lt;br /&gt;
&lt;br /&gt;
[[Category:Plugins]]&lt;/div&gt;</summary>
		<author><name>Mdekker</name></author>
	</entry>
	<entry>
		<id>https://www.limesurvey.org/manual/index.php?title=Authentication_plugins&amp;diff=38259</id>
		<title>Authentication plugins</title>
		<link rel="alternate" type="text/html" href="https://www.limesurvey.org/manual/index.php?title=Authentication_plugins&amp;diff=38259"/>
		<updated>2013-06-11T13:51:15Z</updated>

		<summary type="html">&lt;p&gt;Mdekker: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;An authentication plugin has some additional requirements over a regular plugin. Here we list the requirements.&lt;br /&gt;
&lt;br /&gt;
To make creating your own authentication plugin easier, you should extend the abstract [https://github.com/LimeSurvey/LimeSurvey/blob/2.05/application/libraries/PluginManager/AuthPluginBase.php AuthPluginBase] class.&lt;br /&gt;
[[Category:Plugins]]&lt;/div&gt;</summary>
		<author><name>Mdekker</name></author>
	</entry>
	<entry>
		<id>https://www.limesurvey.org/manual/index.php?title=Authentication_plugins&amp;diff=38258</id>
		<title>Authentication plugins</title>
		<link rel="alternate" type="text/html" href="https://www.limesurvey.org/manual/index.php?title=Authentication_plugins&amp;diff=38258"/>
		<updated>2013-06-11T13:50:42Z</updated>

		<summary type="html">&lt;p&gt;Mdekker: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;An authentication plugin has some additional requirements over a regular plugin. Here we list the requirements.&lt;br /&gt;
&lt;br /&gt;
To make creating your own authentication plugin easier, you should extend the abstract [https://github.com/LimeSurvey/LimeSurvey/blob/2.05/application/libraries/PluginManager/AuthPluginBase.php|AuthPluginBase] class.&lt;br /&gt;
[[Category:Plugins]]&lt;/div&gt;</summary>
		<author><name>Mdekker</name></author>
	</entry>
	<entry>
		<id>https://www.limesurvey.org/manual/index.php?title=Authentication_plugins&amp;diff=38247</id>
		<title>Authentication plugins</title>
		<link rel="alternate" type="text/html" href="https://www.limesurvey.org/manual/index.php?title=Authentication_plugins&amp;diff=38247"/>
		<updated>2013-06-11T13:44:16Z</updated>

		<summary type="html">&lt;p&gt;Mdekker: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;An authentication plugin has some additional requirements over a regular plugin. Here we list the requirements.&lt;br /&gt;
[[Category:Plugins]]&lt;/div&gt;</summary>
		<author><name>Mdekker</name></author>
	</entry>
	<entry>
		<id>https://www.limesurvey.org/manual/index.php?title=Category:Plugins&amp;diff=38246</id>
		<title>Category:Plugins</title>
		<link rel="alternate" type="text/html" href="https://www.limesurvey.org/manual/index.php?title=Category:Plugins&amp;diff=38246"/>
		<updated>2013-06-11T13:43:18Z</updated>

		<summary type="html">&lt;p&gt;Mdekker: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This is an overview of all pages linked to the Plugins category.&lt;br /&gt;
&lt;br /&gt;
[[Category:Development]]&lt;/div&gt;</summary>
		<author><name>Mdekker</name></author>
	</entry>
	<entry>
		<id>https://www.limesurvey.org/manual/index.php?title=Category:Plugins&amp;diff=38245</id>
		<title>Category:Plugins</title>
		<link rel="alternate" type="text/html" href="https://www.limesurvey.org/manual/index.php?title=Category:Plugins&amp;diff=38245"/>
		<updated>2013-06-11T13:42:50Z</updated>

		<summary type="html">&lt;p&gt;Mdekker: Created page with &amp;quot;This is an overview of all pages linked to the Plugins category.&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This is an overview of all pages linked to the Plugins category.&lt;/div&gt;</summary>
		<author><name>Mdekker</name></author>
	</entry>
	<entry>
		<id>https://www.limesurvey.org/manual/index.php?title=Authentication_plugins&amp;diff=38244</id>
		<title>Authentication plugins</title>
		<link rel="alternate" type="text/html" href="https://www.limesurvey.org/manual/index.php?title=Authentication_plugins&amp;diff=38244"/>
		<updated>2013-06-11T13:41:13Z</updated>

		<summary type="html">&lt;p&gt;Mdekker: Created page with &amp;quot;This pages will show information about creating your own authentication plugin Category:Plugins&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This pages will show information about creating your own authentication plugin&lt;br /&gt;
[[Category:Plugins]]&lt;/div&gt;</summary>
		<author><name>Mdekker</name></author>
	</entry>
	<entry>
		<id>https://www.limesurvey.org/manual/index.php?title=Plugins_-_advanced&amp;diff=38242</id>
		<title>Plugins - advanced</title>
		<link rel="alternate" type="text/html" href="https://www.limesurvey.org/manual/index.php?title=Plugins_-_advanced&amp;diff=38242"/>
		<updated>2013-06-11T13:40:23Z</updated>

		<summary type="html">&lt;p&gt;Mdekker: /* Special plugins */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
Starting from LimeSurvey 2.05, LimeSurvey will officially support plugins.&lt;br /&gt;
&lt;br /&gt;
Plugins allow users to customize the functionality of their installation while still being able to benefit from regular software updates.&lt;br /&gt;
&lt;br /&gt;
This documentation is meant for developers that are extending LimeSurvey for their own use or for their clients; end users will not be helped by this documentation.&lt;br /&gt;
&lt;br /&gt;
Plugins must implement the [https://github.com/LimeSurvey/LimeSurvey/blob/2.05/application/libraries/PluginManager/iPlugin.php iPlugin] interface. We recommend&lt;br /&gt;
&lt;br /&gt;
extending your plugin class from the [https://github.com/LimeSurvey/LimeSurvey/blob/2.05/application/libraries/PluginManager/PluginBase.php PluginBase] class.&lt;br /&gt;
&lt;br /&gt;
By extending you benefit from common functionality required by plugins that we already have implemented for you. One of these function is the implementation of the getPluginSettings function. This function must return an array describing the configuration options for the user.&lt;br /&gt;
&lt;br /&gt;
The example plugin exposes just 1 configurable setting, the message it&#039;ll show.&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;
protected $settings = array(&lt;br /&gt;
    &#039;logo&#039; =&amp;gt; array(&lt;br /&gt;
          &#039;type&#039; =&amp;gt; &#039;logo&#039;,&lt;br /&gt;
          &#039;path&#039; =&amp;gt; &#039;assets/logo.png&#039;&lt;br /&gt;
     ),&lt;br /&gt;
&lt;br /&gt;
     &#039;message&#039; =&amp;gt; array(&lt;br /&gt;
          &#039;type&#039; =&amp;gt; &#039;string&#039;,&lt;br /&gt;
          &#039;label&#039; =&amp;gt; &#039;Message&#039;&lt;br /&gt;
     )&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The array contains a name for each setting as a key. The values are arrays containing the required meta data.&lt;br /&gt;
&lt;br /&gt;
Supported types are:&lt;br /&gt;
&lt;br /&gt;
* logo&lt;br /&gt;
* string&lt;br /&gt;
* html&lt;br /&gt;
* choice&lt;br /&gt;
* relevance&lt;br /&gt;
&lt;br /&gt;
Besides type a number of other keys are available:&lt;br /&gt;
&lt;br /&gt;
* label, defines a label (use English, the label specified here will be passed through the translation functions)&lt;br /&gt;
* default, defines a value to show if no value is specified.&lt;br /&gt;
* current, defines the current value.&lt;br /&gt;
* readOnly, specifies the setting is read only.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Special plugins ==&lt;br /&gt;
[[Authentication plugins]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Development]]&lt;br /&gt;
[[Category:Plugins]]&lt;/div&gt;</summary>
		<author><name>Mdekker</name></author>
	</entry>
	<entry>
		<id>https://www.limesurvey.org/manual/index.php?title=Plugins_-_advanced&amp;diff=38240</id>
		<title>Plugins - advanced</title>
		<link rel="alternate" type="text/html" href="https://www.limesurvey.org/manual/index.php?title=Plugins_-_advanced&amp;diff=38240"/>
		<updated>2013-06-11T12:44:30Z</updated>

		<summary type="html">&lt;p&gt;Mdekker: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
Starting from LimeSurvey 2.05, LimeSurvey will officially support plugins.&lt;br /&gt;
&lt;br /&gt;
Plugins allow users to customize the functionality of their installation while still being able to benefit from regular software updates.&lt;br /&gt;
&lt;br /&gt;
This documentation is meant for developers that are extending LimeSurvey for their own use or for their clients; end users will not be helped by this documentation.&lt;br /&gt;
&lt;br /&gt;
Plugins must implement the [https://github.com/LimeSurvey/LimeSurvey/blob/2.05/application/libraries/PluginManager/iPlugin.php iPlugin] interface. We recommend&lt;br /&gt;
&lt;br /&gt;
extending your plugin class from the [https://github.com/LimeSurvey/LimeSurvey/blob/2.05/application/libraries/PluginManager/PluginBase.php PluginBase] class.&lt;br /&gt;
&lt;br /&gt;
By extending you benefit from common functionality required by plugins that we already have implemented for you. One of these function is the implementation of the getPluginSettings function. This function must return an array describing the configuration options for the user.&lt;br /&gt;
&lt;br /&gt;
The example plugin exposes just 1 configurable setting, the message it&#039;ll show.&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;
protected $settings = array(&lt;br /&gt;
    &#039;logo&#039; =&amp;gt; array(&lt;br /&gt;
          &#039;type&#039; =&amp;gt; &#039;logo&#039;,&lt;br /&gt;
          &#039;path&#039; =&amp;gt; &#039;assets/logo.png&#039;&lt;br /&gt;
     ),&lt;br /&gt;
&lt;br /&gt;
     &#039;message&#039; =&amp;gt; array(&lt;br /&gt;
          &#039;type&#039; =&amp;gt; &#039;string&#039;,&lt;br /&gt;
          &#039;label&#039; =&amp;gt; &#039;Message&#039;&lt;br /&gt;
     )&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The array contains a name for each setting as a key. The values are arrays containing the required meta data.&lt;br /&gt;
&lt;br /&gt;
Supported types are:&lt;br /&gt;
&lt;br /&gt;
* logo&lt;br /&gt;
* string&lt;br /&gt;
* html&lt;br /&gt;
* choice&lt;br /&gt;
* relevance&lt;br /&gt;
&lt;br /&gt;
Besides type a number of other keys are available:&lt;br /&gt;
&lt;br /&gt;
* label, defines a label (use English, the label specified here will be passed through the translation functions)&lt;br /&gt;
* default, defines a value to show if no value is specified.&lt;br /&gt;
* current, defines the current value.&lt;br /&gt;
* readOnly, specifies the setting is read only.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Special plugins ==&lt;br /&gt;
[[AuthPlugin|Authentication plugins]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Development]]&lt;br /&gt;
[[Category:Plugins]]&lt;/div&gt;</summary>
		<author><name>Mdekker</name></author>
	</entry>
	<entry>
		<id>https://www.limesurvey.org/manual/index.php?title=Plugins_-_advanced&amp;diff=38239</id>
		<title>Plugins - advanced</title>
		<link rel="alternate" type="text/html" href="https://www.limesurvey.org/manual/index.php?title=Plugins_-_advanced&amp;diff=38239"/>
		<updated>2013-06-11T12:41:18Z</updated>

		<summary type="html">&lt;p&gt;Mdekker: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
Starting from LimeSurvey 2.05, LimeSurvey will officially support plugins.&lt;br /&gt;
&lt;br /&gt;
Plugins allow users to customize the functionality of their installation while still being able to benefit from regular software updates.&lt;br /&gt;
&lt;br /&gt;
This documentation is meant for developers that are extending LimeSurvey for their own use or for their clients; end users will not be helped by this documentation.&lt;br /&gt;
&lt;br /&gt;
Plugins must implement the [https://github.com/LimeSurvey/LimeSurvey/blob/2.05/application/libraries/PluginManager/iPlugin.php iPlugin] interface. We recommend&lt;br /&gt;
&lt;br /&gt;
extending your plugin class from the [https://github.com/LimeSurvey/LimeSurvey/blob/2.05/application/libraries/PluginManager/PluginBase.php PluginBase] class.&lt;br /&gt;
&lt;br /&gt;
By extending you benefit from common functionality required by plugins that we already have implemented for you. One of these function is the implementation of the getPluginSettings function. This function must return an array describing the configuration options for the user.&lt;br /&gt;
&lt;br /&gt;
The example plugin exposes just 1 configurable setting, the message it&#039;ll show.&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;
protected $settings = array(&lt;br /&gt;
    &#039;logo&#039; =&amp;gt; array(&lt;br /&gt;
          &#039;type&#039; =&amp;gt; &#039;logo&#039;,&lt;br /&gt;
          &#039;path&#039; =&amp;gt; &#039;assets/logo.png&#039;&lt;br /&gt;
     ),&lt;br /&gt;
&lt;br /&gt;
     &#039;message&#039; =&amp;gt; array(&lt;br /&gt;
          &#039;type&#039; =&amp;gt; &#039;string&#039;,&lt;br /&gt;
          &#039;label&#039; =&amp;gt; &#039;Message&#039;&lt;br /&gt;
     )&lt;br /&gt;
);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The array contains a name for each setting as a key. The values are arrays containing the required meta data.&lt;br /&gt;
&lt;br /&gt;
Supported types are:&lt;br /&gt;
&lt;br /&gt;
* logo&lt;br /&gt;
* string&lt;br /&gt;
* html&lt;br /&gt;
* choice&lt;br /&gt;
* relevance&lt;br /&gt;
&lt;br /&gt;
Besides type a number of other keys are available:&lt;br /&gt;
&lt;br /&gt;
* label, defines a label (use English, the label specified here will be passed through the translation functions)&lt;br /&gt;
* default, defines a value to show if no value is specified.&lt;br /&gt;
* current, defines the current value.&lt;br /&gt;
* readOnly, specifies the setting is read only.&lt;br /&gt;
&lt;br /&gt;
[[Category:Development]]&lt;br /&gt;
[[Category:Plugins]]&lt;/div&gt;</summary>
		<author><name>Mdekker</name></author>
	</entry>
	<entry>
		<id>https://www.limesurvey.org/manual/index.php?title=Expression_Manager&amp;diff=31260</id>
		<title>Expression Manager</title>
		<link rel="alternate" type="text/html" href="https://www.limesurvey.org/manual/index.php?title=Expression_Manager&amp;diff=31260"/>
		<updated>2013-06-04T14:16:46Z</updated>

		<summary type="html">&lt;p&gt;Mdekker: Removed underscore for comment fields&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 an 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, weight_kg 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 (e.g. &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 1.92 and later 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;SGQA&#039;&#039;&#039;:  This is how variables are named in LimeSurvey &amp;lt;= 1.91+&lt;br /&gt;
#*Stands for Survey-Group-Question-Answer&lt;br /&gt;
#*SGQA variable names look like 123X5X382X971, and may have sub-question suffixes.&lt;br /&gt;
#*These variable names are specific to the underlying S/Q/G/A database codes, so often need to be changed&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;
#*Although not required to be unique in &amp;lt;= 1.91+, it must be unique if you want to use EM&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 chldren&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;
#*Eveything 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 1.92+ 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;
**Availalbe Functions lists the 70+ functions and syntax&lt;br /&gt;
**Unit Tests of Isolsted 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 diplayed. 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 and 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 deterimine 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;
Expression Manager supports the following syntax:&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;
&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;
{|&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;
|}&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 sould 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;
&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;
&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)&lt;br /&gt;
*INSERTANS:SGQA - the display value of an answer (e.g. &amp;quot;Yes&amp;quot;)&lt;br /&gt;
*All {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:149--&amp;gt;&lt;br /&gt;
Furthermore, Expression Manager lets you access many properties of the Question:&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;
=== Security issue=== &amp;lt;!--T:151--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:152--&amp;gt;&lt;br /&gt;
For security issues, text entered by user are filtered. Some caracter 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;
==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; . AnswerID . &#039;_&#039; . ScaleId&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|| || ||{Q22_E}||{Q22_E.shown}||{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.&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;
==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;
|[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 (in last 2.0 version)||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 string||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 a string||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)&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 a 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 &#039;&#039; 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 converage 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;
|blue bold text||style=&#039;color:blue; background-color:#eee8aa&#039;|&#039;&#039;&#039;Sample&#039;&#039;&#039;||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:grey; background-color:#eee8aa&#039;|Sample||string||none||single and double-quoted strings are shown in grey text&lt;br /&gt;
|-&lt;br /&gt;
|bold maroon text||style=&#039;color:maroon; background-color:#eee8aa&#039;|&#039;&#039;&#039;Sample&#039;&#039;&#039;||variable set on the same page, but after the current question||&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 but after the current question is shown in bold maroon text.  This color coding should alert authors to possible errors in question sequencing; but it is allowed since some authors may want this sequence of variables a page, especially for dynamic reports.  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 cyan text||style=&#039;color:#4C88BE; background-color:#eee8aa&#039;|&#039;&#039;&#039;Sample&#039;&#039;&#039;||variable set on the same page, prior to the current question||&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 and prior to the current question is shown in bold cyan 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 green text||style=&#039;color:green; background-color:#eee8aa&#039;|&#039;&#039;&#039;Sample&#039;&#039;&#039;||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 pageis 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:#FF00FF; background-color:#eee8aa&#039;|&#039;&#039;&#039;Sample&#039;&#039;&#039;||variable set on a later 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 pageis 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:#996600; background-color:#eee8aa&#039;|&#039;&#039;&#039;Sample&#039;&#039;&#039;||a lime relacement value||the value||Lime Replacement Strings (like {TOKEN:xxx}, {PRIVACY_MESSAGE} are shown in bold tan text.  The tooltip shows the current value.&lt;br /&gt;
|-&lt;br /&gt;
|red text||style=&#039;color:red; 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;
=Relationship to LimeSurvey Ideas / Feature Requests= &amp;lt;!--T:200--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:201--&amp;gt;&lt;br /&gt;
Expression Manager provides complete or partial solutions to each of the following:&lt;br /&gt;
*[http://ideas.limesurvey.org/ideatorrent/idea/1 Conditions]&lt;br /&gt;
*[http://ideas.limesurvey.org/ideatorrent/idea/3/ Answercounts]&lt;br /&gt;
*[http://ideas.limesurvey.org/ideatorrent/idea/5 Advanced reporting for assessments]&lt;br /&gt;
**partial: Equations let one store the Assessment value in the database, and micro-tailoring can generate simple formatted reports.  Authors can access those Equation values if they have more complex reporting needs.&lt;br /&gt;
*[http://ideas.limesurvey.org/ideatorrent/idea/6 Assessment reports]&lt;br /&gt;
**partial:  Since Equations store the Assessment score, it should be possible to use Statistics to show distributions of those scores, and Quotas to limit the number of responses with those scores.&lt;br /&gt;
*[http://ideas.limesurvey.org/ideatorrent/idea/7 Store assessment results for further evaluation]&lt;br /&gt;
**Equations let one store the Assessment value in the database, completely solving this problem&lt;br /&gt;
*[http://ideas.limesurvey.org/ideatorrent/idea/22/ More advanced condition rules]&lt;br /&gt;
*[http://ideas.limesurvey.org/ideatorrent/idea/28 Open Answertable up so that we can alter formatting]&lt;br /&gt;
**partial:  All of the question attributes are available, so authors can create custom AnswerTable equivalents as a Question.  Once implatemented, they can also use the showTheseResponses() or showAllResponsesExecpt() functions&lt;br /&gt;
*[http://ideas.limesurvey.org/ideatorrent/idea/37 Export survey results with full questions to include images]&lt;br /&gt;
**since Tailoring has access to the full question text, it can include images in the export&lt;br /&gt;
**if subjects choose Print Your Answers after finishing the survey, those printouts will be fully tailored&lt;br /&gt;
*[http://ideas.limesurvey.org/ideatorrent/idea/63 List of question codes and SGQA identifiers]&lt;br /&gt;
**The Show Survey Logic view shows that mapping (plus much more information)&lt;br /&gt;
**In addition, you no longer have to use SGQA codes to refer to variables - you can use the Question code/title.&lt;br /&gt;
*[http://ideas.limesurvey.org/ideatorrent/idea/69 Branch/jump to another question (earlier or later) based on current question]&lt;br /&gt;
**You can use the Navigation Index for this in most cases&lt;br /&gt;
**Once implemented, you can use the JumpTo() function.  Like the Navigation Index, if you try to jump forward, it will stop on an intervening page if there are any of the relevant mandatory questions are unanswered, or if any relevant questions fail validation tests.&lt;br /&gt;
*[http://ideas.limesurvey.org/ideatorrent/idea/86 set quota for total responses]&lt;br /&gt;
**If the final question is an Equation that flags a survey as completed (so is NULL if a respondant does not get to that page), you can use Quotas on that question to control the number of completed responses.&lt;br /&gt;
*[http://ideas.limesurvey.org/ideatorrent/idea/101 Review all conditions]&lt;br /&gt;
**The [[Show Logic File|Show Logic File]] view shows this (and much more)&lt;br /&gt;
*[http://ideas.limesurvey.org/ideatorrent/idea/105 Review all questions + Review all groups]&lt;br /&gt;
**The [[Show Logic File|Show Logic File]] view shows this (and much more)&lt;br /&gt;
*[http://ideas.limesurvey.org/ideatorrent/idea/107 How to visualize questions, logic &amp;amp; conditions]&lt;br /&gt;
**The [[Show Logic File|Show Logic File]] view shows this (and much more)&lt;br /&gt;
*[http://ideas.limesurvey.org/ideatorrent/idea/113 Offline Surveys]&lt;br /&gt;
**Running a survey with all of the questions on the same page would let you do off-line data collection  (e.g. email the html page and associated JavaScript).  However, you would still want a way to submit the results so that they did not get lost.  It may be possible to use Save As HTML to save partially completed responses.&lt;br /&gt;
*[http://ideas.limesurvey.org/ideatorrent/idea/120 Remove INSERTANS from question text at survey results]&lt;br /&gt;
**INSERTANS is no longer needed.  You can refer to a variable by its SGQA code (without prefixing it with INSERTANS:), or by its question code.&lt;br /&gt;
*[http://ideas.limesurvey.org/ideatorrent/idea/137 Informed Consent and Authorization Functionality]&lt;br /&gt;
**You can show show the informed consent on the welcome page, then ask any additional questions needed (to ensure they meet the study inclusion/exclusion criteria), and ask them a Yes/No question whether they give their consent.  Then, make all of the remaining questions conditional on that yesNo.  For example, if the question is named &#039;&#039;consent&#039;&#039;, you would set the relevance to the remaining questions to &#039;&#039;consent == &amp;quot;Y&amp;quot;&#039;&#039; (possibly &#039;&#039;and&#039;&#039;ing that with whatever additional conditions you needed to support your branching needs.&lt;br /&gt;
*[http://ideas.limesurvey.org/ideatorrent/idea/199 Show codes instead of of answers using INSERTANS]&lt;br /&gt;
**{Qcode} returns the code instead of the response text (which you can get via {INSERTANS:SGQA}, or {Qcode.shown}&lt;br /&gt;
*[http://ideas.limesurvey.org/ideatorrent/idea/204 Need group mean or calculations for assessments]&lt;br /&gt;
**Say you have N variables of which N-X were answered, you could compute the mean of the answered variables as {sum(var1, var2, ..., varN) / count(var1, var2, ..., varN)}&lt;br /&gt;
**Computing the mean across a set of respondants would require extension of the Quota functionality.&lt;br /&gt;
*[http://ideas.limesurvey.org/ideatorrent/idea/222 To insert a language dependent text]&lt;br /&gt;
**Tailoring lets you conjugate verbs and decline nouns in each language&lt;br /&gt;
*[http://ideas.limesurvey.org/ideatorrent/idea/225 Surveyors should approve their answers]&lt;br /&gt;
**Custom Questions with tailoring, or the showAllResponsesExcept() function will let Surveyors see all of the questions and responses before clicking Submit. If the Navigation Menu option is enabled, it is easy to go back and correct answers.&lt;br /&gt;
*[http://ideas.limesurvey.org/ideatorrent/idea/1.92 Suppliment to #answernnXnnXnnn method of targetting form elements]&lt;br /&gt;
**You can now refer to questions and answers by their Question Code, so there is no longer a need to modify SGQA values.&lt;br /&gt;
*[http://ideas.limesurvey.org/ideatorrent/idea/262 More flexibility with hidden questions]&lt;br /&gt;
*[http://ideas.limesurvey.org/ideatorrent/idea/265 Remove specific conditions from multiple questions]&lt;br /&gt;
**You can now use Relevance, which is easier to manage than Conditions.  If  needed, they can all be exported from the database, edited in a spreadsheet, and re-imported.&lt;br /&gt;
*[http://ideas.limesurvey.org/ideatorrent/idea/268 Cross Survey Reporting]&lt;br /&gt;
**By using question codes that are unique across your surveys and versions, you can consolidate data from multiple surveys and/or compare them&lt;br /&gt;
*[http://ideas.limesurvey.org/ideatorrent/idea/275 Simplifying integration with other tools]&lt;br /&gt;
**Expression Manager uses Question Codes instead of SGQA, making it easier to integrate with other tools.&lt;br /&gt;
*[http://ideas.limesurvey.org/ideatorrent/idea/1.92 Expose assessment score to 3rd party app processing]&lt;br /&gt;
**This can be done with Equation question type&lt;br /&gt;
*[http://ideas.limesurvey.org/ideatorrent/idea/309 Multiple thank you pages]&lt;br /&gt;
**This can be supported via conditional relevance branching and tailoring&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>Mdekker</name></author>
	</entry>
	<entry>
		<id>https://www.limesurvey.org/manual/index.php?title=LimeSurvey_roadmap&amp;diff=17597</id>
		<title>LimeSurvey roadmap</title>
		<link rel="alternate" type="text/html" href="https://www.limesurvey.org/manual/index.php?title=LimeSurvey_roadmap&amp;diff=17597"/>
		<updated>2013-04-19T13:55:20Z</updated>

		<summary type="html">&lt;p&gt;Mdekker: &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;
Contents:__TOC__&lt;br /&gt;
&lt;br /&gt;
=General= &amp;lt;!--T:2--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:3--&amp;gt;&lt;br /&gt;
This page lists future development and release goals. We will update this regularly with more details as they become available. Goals cannot be fulfill by itself so if you want to give a helping hand please get in touch! Following you will find our first public project status and any future project status will replace this one. All project statuses can/will be found on the[[Past project statuses]] page.&lt;br /&gt;
&lt;br /&gt;
=LimeSurvey project status January 4th, 2013= &amp;lt;!--T:4--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:5--&amp;gt;&lt;br /&gt;
LimeSurvey 2.0+ is currently considered to be stable - due to the recent switch to the Yii framework there are certain issues coming up regarding cross-DB compatibilities which are addressed by regular releases of new builds. LimeSurvey 2.1 is currenty in development and will show the start of a plugin-architecture.&lt;br /&gt;
&lt;br /&gt;
=Timeline= &amp;lt;!--T:6--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:7--&amp;gt;&lt;br /&gt;
{|&lt;br /&gt;
|Est. date||Goal||Remarks/features&lt;br /&gt;
|-&lt;br /&gt;
|15 April 2013||Release 2.1 alpha version||-Improved plug-in system&amp;lt;br/&amp;gt;-Question types are now plugins&lt;br /&gt;
|-&lt;br /&gt;
|Unknown||Release 2.2||- New question designer&amp;lt;br/&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|Unknown||Release 2.3||- Locking&amp;lt;br/&amp;gt;- Trans-process caching&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/translate&amp;gt;&lt;br /&gt;
[[Development::start]]&lt;/div&gt;</summary>
		<author><name>Mdekker</name></author>
	</entry>
	<entry>
		<id>https://www.limesurvey.org/manual/index.php?title=Category:Development&amp;diff=17596</id>
		<title>Category:Development</title>
		<link rel="alternate" type="text/html" href="https://www.limesurvey.org/manual/index.php?title=Category:Development&amp;diff=17596"/>
		<updated>2013-04-19T13:53:58Z</updated>

		<summary type="html">&lt;p&gt;Mdekker: Created page with &amp;quot;This is an overview of all pages linked to the Development category&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This is an overview of all pages linked to the Development category&lt;/div&gt;</summary>
		<author><name>Mdekker</name></author>
	</entry>
	<entry>
		<id>https://www.limesurvey.org/manual/index.php?title=LimeSurvey_roadmap&amp;diff=17595</id>
		<title>LimeSurvey roadmap</title>
		<link rel="alternate" type="text/html" href="https://www.limesurvey.org/manual/index.php?title=LimeSurvey_roadmap&amp;diff=17595"/>
		<updated>2013-04-19T13:51:15Z</updated>

		<summary type="html">&lt;p&gt;Mdekker: &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;
Contents:__TOC__&lt;br /&gt;
&lt;br /&gt;
=General= &amp;lt;!--T:2--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:3--&amp;gt;&lt;br /&gt;
This page lists future development and release goals. We will update this regularly with more details as they become available. Goals cannot be fulfill by itself so if you want to give a helping hand please get in touch! Following you will find our first public project status and any future project status will replace this one. All project statuses can/will be found on the[[Past project statuses]] page.&lt;br /&gt;
&lt;br /&gt;
=LimeSurvey project status January 4th, 2013= &amp;lt;!--T:4--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:5--&amp;gt;&lt;br /&gt;
LimeSurvey 2.0+ is currently considered to be stable - due to the recent switch to the Yii framework there are certain issues coming up regarding cross-DB compatibilities which are addressed by regular releases of new builds. LimeSurvey 2.1 is currenty in development and will show the start of a plugin-architecture.&lt;br /&gt;
&lt;br /&gt;
=Timeline= &amp;lt;!--T:6--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:7--&amp;gt;&lt;br /&gt;
{|&lt;br /&gt;
|Est. date||Goal||Remarks/features&lt;br /&gt;
|-&lt;br /&gt;
|15 April 2013||Release 2.1 alpha version||-Improved plug-in system&amp;lt;br/&amp;gt;-Question types are now plugins&lt;br /&gt;
|-&lt;br /&gt;
|Unknown||Release 2.2||- New question designer&amp;lt;br/&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|Unknown||Release 2.3||- Locking&amp;lt;br/&amp;gt;- Trans-process caching&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/translate&amp;gt;&lt;br /&gt;
[[Category:Development]]&lt;/div&gt;</summary>
		<author><name>Mdekker</name></author>
	</entry>
	<entry>
		<id>https://www.limesurvey.org/manual/index.php?title=Expression_Manager&amp;diff=4467</id>
		<title>Expression Manager</title>
		<link rel="alternate" type="text/html" href="https://www.limesurvey.org/manual/index.php?title=Expression_Manager&amp;diff=4467"/>
		<updated>2013-01-31T12:57:48Z</updated>

		<summary type="html">&lt;p&gt;Mdekker: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
__TOC__&lt;br /&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=&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&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;
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;
The following sections show the main places where Expression Manager is used&lt;br /&gt;
&lt;br /&gt;
==Relevance (Controlling Navigation/Branching)==&lt;br /&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 an 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;
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, weight_kg 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;
[[File:tutorial1.jpg]]&lt;br /&gt;
&lt;br /&gt;
Relevance is shown and editable in the following places:&lt;br /&gt;
&lt;br /&gt;
===Viewing / Editing Question-Level Relevance===&lt;br /&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;
[[File:tutorial2.jpg]]&lt;br /&gt;
&lt;br /&gt;
This is the edit screen for the BMI question.&lt;br /&gt;
&lt;br /&gt;
[[File:tutorial3.jpg]]&lt;br /&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===&lt;br /&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;
[[File:tutorial4.jpg]]&lt;br /&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;
Here is the screen for editing the group-level relevance for that question:&lt;br /&gt;
&lt;br /&gt;
[[File:tutorial5.jpg]]&lt;br /&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==&lt;br /&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===&lt;br /&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;
[[File:tailoring7.jpg]]&lt;br /&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;
BMI computes the weight formula as {weight_kg / (height_m * height_m)}.&lt;br /&gt;
&lt;br /&gt;
Lastly, the report conditionally tailors the message for the subject, telling him what he entered (e.g. &amp;quot;You said you are 2 meters tall and weight 70 kg.&amp;quot;&lt;br /&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;
[[File:tailoring8.jpg]]&lt;br /&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;
[[File:tailoring9.jpg]]&lt;br /&gt;
&lt;br /&gt;
===Tailored Questions, Answers, and Reports===&lt;br /&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;span&amp;gt; tag which is not valid inside select options.&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This example shows the BMI report.&lt;br /&gt;
&lt;br /&gt;
[[File:tailoring10.jpg]]&lt;br /&gt;
&lt;br /&gt;
Here is the edit window for the same question.&lt;br /&gt;
&lt;br /&gt;
[[File:tailoring11.jpg]]&lt;br /&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;
[[File:tailoring12.jpg]]&lt;br /&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;
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==&lt;br /&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;
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;
The [[Expression Manager Sample Surveys|Sample Surveys]] pages shows many working examples of using expressions for validations.&lt;br /&gt;
&lt;br /&gt;
=Introduction=&lt;br /&gt;
&lt;br /&gt;
LimeSurvey 1.92 and later 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;
This wiki page is the definitive reference for Expression Manager syntax and functionality.&lt;br /&gt;
&lt;br /&gt;
==Key Definitions==&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;SGQA&#039;&#039;&#039;:  This is how variables are named in LimeSurvey &amp;lt;= 1.91+&lt;br /&gt;
**Stands for Survey-Group-Question-Answer&lt;br /&gt;
**SGQA variable names look like 123X5X382X971, and may have sub-question suffixes.&lt;br /&gt;
**These variable names are specific to the underlying S/Q/G/A database codes, so often need to be changed&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;
**Although not required to be unique in &amp;lt;= 1.91+, it must be unique if you want to use EM&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?==&lt;br /&gt;
&lt;br /&gt;
The short answer is No (but also yes).&lt;br /&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;
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;
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?==&lt;br /&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;
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?==&lt;br /&gt;
&lt;br /&gt;
Here is a list of pros and cons of each style:&lt;br /&gt;
&lt;br /&gt;
{|&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;
|}&lt;br /&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?==&lt;br /&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 chldren&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?==&lt;br /&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;
**Eveything 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+?==&lt;br /&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;
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=&lt;br /&gt;
&lt;br /&gt;
The best way to get started with EM is to:&lt;br /&gt;
*Install 1.92+ 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;
**Availalbe Functions lists the 70+ functions and syntax&lt;br /&gt;
**Unit Tests of Isolsted 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+)=&lt;br /&gt;
&lt;br /&gt;
==Conditions =&amp;gt; Relevance==&lt;br /&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==&lt;br /&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==&lt;br /&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==&lt;br /&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==&lt;br /&gt;
&lt;br /&gt;
Equations were not supported without fancy JavaScript.&lt;br /&gt;
&lt;br /&gt;
==Equation Question Type==&lt;br /&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?=&lt;br /&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)==&lt;br /&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===&lt;br /&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 diplayed. 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;
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;
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;
{|&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;
|}&lt;br /&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;
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 and 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===&lt;br /&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 deterimine 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===&lt;br /&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;
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===&lt;br /&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;
This solves a common request for storing Assessment scores within the database&lt;br /&gt;
&lt;br /&gt;
==Syntax==&lt;br /&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;
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;syntaxhighlight lang=&amp;quot;java&amp;quot; enclose=&amp;quot;div&amp;quot;&amp;gt;{if(is_empty(PFTotals),&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;,&lt;br /&gt;
&lt;br /&gt;
 if(PFTotals &amp;gt;= -5 &amp;amp;&amp;amp; PFTotals &amp;lt;= -4,&lt;br /&gt;
&lt;br /&gt;
   &#039;Very Soft&#039;,&lt;br /&gt;
&lt;br /&gt;
   if(PFTotals &amp;gt;= -3 &amp;amp;&amp;amp; PFTotals &amp;lt;= -2,&lt;br /&gt;
&lt;br /&gt;
     &#039;Soft&#039;,&lt;br /&gt;
&lt;br /&gt;
     if(PFTotals == -1,&lt;br /&gt;
&lt;br /&gt;
       &#039;Somewhat Soft&#039;,&lt;br /&gt;
&lt;br /&gt;
       if(PFTotals == 0,&lt;br /&gt;
&lt;br /&gt;
         &#039;Moderate&#039;,&lt;br /&gt;
&lt;br /&gt;
         if(PFTotals == 1,&lt;br /&gt;
&lt;br /&gt;
           &#039;Somewhat Hard&#039;,&lt;br /&gt;
&lt;br /&gt;
           if(PFTotals &amp;gt;= 2 &amp;amp;&amp;amp; PFTotals &amp;lt;= 3,&lt;br /&gt;
&lt;br /&gt;
             &#039;Hard&#039;,&lt;br /&gt;
&lt;br /&gt;
             if(PFTotals &amp;gt;= 4 &amp;amp;&amp;amp; PFTotals &amp;lt;= 5,&lt;br /&gt;
&lt;br /&gt;
               &#039;Very Hard&#039;,&lt;br /&gt;
&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;
&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;
Expression Manager supports the following syntax:&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;
EM syntax follows normal operator precedence:&lt;br /&gt;
&lt;br /&gt;
{|&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;
|}&lt;br /&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 (=)===&lt;br /&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 sould 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;
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;
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;
&lt;br /&gt;
==Access to Variables==&lt;br /&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)&lt;br /&gt;
*INSERTANS:SGQA - the display value of an answer (e.g. &amp;quot;Yes&amp;quot;)&lt;br /&gt;
*All {XXX} values used by templates&lt;br /&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;
Furthermore, Expression Manager lets you access many properties of the Question:&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|Syntax||Meaning||Example||Example Result&lt;br /&gt;
|-&lt;br /&gt;
|Qcode||an alias for Qcode.code||{join(&#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||{join(&#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||{join(&#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;
|}&lt;br /&gt;
&lt;br /&gt;
=== Security issue===&lt;br /&gt;
&lt;br /&gt;
For security issue, text entered by user are filtered. Some caracter are replaced by HTML entities.&lt;br /&gt;
* &amp;amp; by &amp;amp;amp;&lt;br /&gt;
* &amp;lt; by &amp;amp;lt;&lt;br /&gt;
* &amp;gt; by &amp;amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Qcode Variable Naming==&lt;br /&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;
QuestionCode . &#039;_&#039; . AnswerID . &#039;_&#039; . ScaleId&lt;br /&gt;
&lt;br /&gt;
{|&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},{Q20_comment}||{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|| || ||{Q22_E}||{Q22_E.shown}||{Q22_E==&#039;Y&#039;}&lt;br /&gt;
|-&lt;br /&gt;
|P||Multiple Choice With Comments Checkbox + Text||Q23||A-F|| || ||{Q23_D}, {Q23_D_comment}||{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;
|}&lt;br /&gt;
&lt;br /&gt;
==The reserved &#039;this&#039;, &#039;self&#039;, and &#039;that&#039; variables==&lt;br /&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;
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;
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;
&#039;&#039;suffix&#039;&#039; is any of the normal qcode suffixes (e.g. NAOK, value, shown)&lt;br /&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.&lt;br /&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;
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;
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;
&#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;
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;
The &#039;self&#039; and &#039;that&#039; variables can be used in any relevance,  validation, or tailoring.&lt;br /&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;
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;
==Access to Functions==&lt;br /&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===&lt;br /&gt;
&lt;br /&gt;
The following functions are currently available:&lt;br /&gt;
&lt;br /&gt;
{|&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;
 [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;
|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]||Natural logarithm||number log(number)&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 string||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 a string||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)&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.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 a 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;
|}&lt;br /&gt;
&lt;br /&gt;
===Functions that are Planned or Being Considered===&lt;br /&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;
{|&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;
|}&lt;br /&gt;
&lt;br /&gt;
==Expression Manager Knows Which Variables are Local==&lt;br /&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==&lt;br /&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;
{|&lt;br /&gt;
|Operator||Example||a||b||Result&lt;br /&gt;
|-&lt;br /&gt;
|+ (unary)||+a||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;
|+||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;
|}&lt;br /&gt;
&lt;br /&gt;
===Overriding Cascading Conditions===&lt;br /&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;
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 &#039;&#039; 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;
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;
The use of the .NAOK suffix also lets authors design surveys that have several possible paths but then converage 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?==&lt;br /&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;
{|&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;
|}&lt;br /&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;
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==&lt;br /&gt;
&lt;br /&gt;
{|&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;
|}&lt;br /&gt;
&lt;br /&gt;
=Syntax Highlighting=&lt;br /&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==&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|Color||Sample||Meaning||Tooltip||Comments&lt;br /&gt;
|-&lt;br /&gt;
|tan background||&amp;lt;span style=&#039;color:#eee8aa,#eee8aa&#039;&amp;gt;Sample&amp;lt;/span&amp;gt;||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;
|blue bold text||&#039;&#039;&#039;&amp;lt;span style=&#039;color:blue,#eee8aa&#039;&amp;gt;Sample&amp;lt;/span&amp;gt;&#039;&#039;&#039;||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||&amp;lt;span style=&#039;color:grey,#eee8aa&#039;&amp;gt;&#039;Sample&#039;&amp;lt;/span&amp;gt;||string||none||single and double-quoted strings are shown in grey text&lt;br /&gt;
|-&lt;br /&gt;
|bold maroon text||&#039;&#039;&#039;&amp;lt;span style=&#039;color:maroon,#eee8aa&#039;&amp;gt;Sample&amp;lt;/span&amp;gt;&#039;&#039;&#039;||variable set on the same page, but after the current question||&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 but after the current question is shown in bold maroon text.  This color coding should alert authors to possible errors in question sequencing; but it is allowed since some authors may want this sequence of variables a page, especially for dynamic reports.  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 cyan text||&#039;&#039;&#039;&amp;lt;span style=&#039;color:#4C88BE,#eee8aa&#039;&amp;gt;Sample&amp;lt;/span&amp;gt;&#039;&#039;&#039;||variable set on the same page, prior to the current question||&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 and prior to the current question is shown in bold cyan 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 green text||&#039;&#039;&#039;&amp;lt;span style=&#039;color:green,#eee8aa&#039;&amp;gt;Sample&amp;lt;/span&amp;gt;&#039;&#039;&#039;||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 pageis 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||&#039;&#039;&#039;&amp;lt;span style=&#039;color:#FF00FF,#eee8aa&#039;&amp;gt;Sample&amp;lt;/span&amp;gt;&#039;&#039;&#039;||variable set on a later 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 pageis 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||&#039;&#039;&#039;&amp;lt;span style=&#039;color:#996600,#eee8aa&#039;&amp;gt;Sample&amp;lt;/span&amp;gt;&#039;&#039;&#039;||a lime relacement value||the value||Lime Replacement Strings (like {TOKEN:xxx}, {PRIVACY_MESSAGE} are shown in bold tan text.  The tooltip shows the current value.&lt;br /&gt;
|-&lt;br /&gt;
|red text||&#039;&#039;&#039;&amp;lt;span style=&#039;color:red,#eee8aa&#039;&amp;gt;Sample&amp;lt;/span&amp;gt;&#039;&#039;&#039;||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||&amp;lt;span style=&#039;color:black,#eee8aa&#039;&amp;gt;Sample&amp;lt;/span&amp;gt;||punctuation||none||All other punctionation 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;
|}&lt;br /&gt;
&lt;br /&gt;
=Relationship to LimeSurvey Ideas / Feature Requests=&lt;br /&gt;
&lt;br /&gt;
Expression Manager provides complete or partial solutions to each of the following:&lt;br /&gt;
*[http://ideas.limesurvey.org/ideatorrent/idea/1 Conditions]&lt;br /&gt;
*[http://ideas.limesurvey.org/ideatorrent/idea/3/ Answercounts]&lt;br /&gt;
*[http://ideas.limesurvey.org/ideatorrent/idea/5 Advanced reporting for assessments]&lt;br /&gt;
**partial: Equations let one store the Assessment value in the database, and micro-tailoring can generate simple formatted reports.  Authors can access those Equation values if they have more complex reporting needs.&lt;br /&gt;
*[http://ideas.limesurvey.org/ideatorrent/idea/6 Assessment reports]&lt;br /&gt;
**partial:  Since Equations store the Assessment score, it should be possible to use Statistics to show distributions of those scores, and Quotas to limit the number of responses with those scores.&lt;br /&gt;
*[http://ideas.limesurvey.org/ideatorrent/idea/7 Store assessment results for further evaluation]&lt;br /&gt;
**Equations let one store the Assessment value in the database, completely solving this problem&lt;br /&gt;
*[http://ideas.limesurvey.org/ideatorrent/idea/22/ More advanced condition rules]&lt;br /&gt;
*[http://ideas.limesurvey.org/ideatorrent/idea/28 Open Answertable up so that we can alter formatting]&lt;br /&gt;
**partial:  All of the question attributes are available, so authors can create custom AnswerTable equivalents as a Question.  Once implatemented, they can also use the showTheseResponses() or showAllResponsesExecpt() functions&lt;br /&gt;
*[http://ideas.limesurvey.org/ideatorrent/idea/37 Export survey results with full questions to include images]&lt;br /&gt;
**since Tailoring has access to the full question text, it can include images in the export&lt;br /&gt;
**if subjects choose Print Your Answers after finishing the survey, those printouts will be fully tailored&lt;br /&gt;
*[http://ideas.limesurvey.org/ideatorrent/idea/63 List of question codes and SGQA identifiers]&lt;br /&gt;
**The Show Survey Logic view shows that mapping (plus much more information)&lt;br /&gt;
**In addition, you no longer have to use SGQA codes to refer to variables - you can use the Question code/title.&lt;br /&gt;
*[http://ideas.limesurvey.org/ideatorrent/idea/69 Branch/jump to another question (earlier or later) based on current question]&lt;br /&gt;
**You can use the Navigation Index for this in most cases&lt;br /&gt;
**Once implemented, you can use the JumpTo() function.  Like the Navigation Index, if you try to jump forward, it will stop on an intervening page if there are any of the relevant mandatory questions are unanswered, or if any relevant questions fail validation tests.&lt;br /&gt;
*[http://ideas.limesurvey.org/ideatorrent/idea/86 set quota for total responses]&lt;br /&gt;
**If the final question is an Equation that flags a survey as completed (so is NULL if a respondant does not get to that page), you can use Quotas on that question to control the number of completed responses.&lt;br /&gt;
*[http://ideas.limesurvey.org/ideatorrent/idea/101 Review all conditions]&lt;br /&gt;
**The [[Show Logic File|Show Logic File]] view shows this (and much more)&lt;br /&gt;
*[http://ideas.limesurvey.org/ideatorrent/idea/105 Review all questions + Review all groups]&lt;br /&gt;
**The [[Show Logic File|Show Logic File]] view shows this (and much more)&lt;br /&gt;
*[http://ideas.limesurvey.org/ideatorrent/idea/107 How to visualize questions, logic &amp;amp; conditions]&lt;br /&gt;
**The [[Show Logic File|Show Logic File]] view shows this (and much more)&lt;br /&gt;
*[http://ideas.limesurvey.org/ideatorrent/idea/113 Offline Surveys]&lt;br /&gt;
**Running a survey with all of the questions on the same page would let you do off-line data collection  (e.g. email the html page and associated JavaScript).  However, you would still want a way to submit the results so that they did not get lost.  It may be possible to use Save As HTML to save partially completed responses.&lt;br /&gt;
*[http://ideas.limesurvey.org/ideatorrent/idea/120 Remove INSERTANS from question text at survey results]&lt;br /&gt;
**INSERTANS is no longer needed.  You can refer to a variable by its SGQA code (without prefixing it with INSERTANS:), or by its question code.&lt;br /&gt;
*[http://ideas.limesurvey.org/ideatorrent/idea/137 Informed Consent and Authorization Functionality]&lt;br /&gt;
**You can show show the informed consent on the welcome page, then ask any additional questions needed (to ensure they meet the study inclusion/exclusion criteria), and ask them a Yes/No question whether they give their consent.  Then, make all of the remaining questions conditional on that yesNo.  For example, if the question is named &#039;&#039;consent&#039;&#039;, you would set the relevance to the remaining questions to &#039;&#039;consent == &amp;quot;Y&amp;quot;&#039;&#039; (possibly &#039;&#039;and&#039;&#039;ing that with whatever additional conditions you needed to support your branching needs.&lt;br /&gt;
*[http://ideas.limesurvey.org/ideatorrent/idea/199 Show codes instead of of answers using INSERTANS]&lt;br /&gt;
**{Qcode} returns the code instead of the response text (which you can get via {INSERTANS:SGQA}, or {Qcode.shown}&lt;br /&gt;
*[http://ideas.limesurvey.org/ideatorrent/idea/204 Need group mean or calculations for assessments]&lt;br /&gt;
**Say you have N variables of which N-X were answered, you could compute the mean of the answered variables as {sum(var1, var2, ..., varN) / count(var1, var2, ..., varN)}&lt;br /&gt;
**Computing the mean across a set of respondants would require extension of the Quota functionality.&lt;br /&gt;
*[http://ideas.limesurvey.org/ideatorrent/idea/222 To insert a language dependent text]&lt;br /&gt;
**Tailoring lets you conjugate verbs and decline nouns in each language&lt;br /&gt;
*[http://ideas.limesurvey.org/ideatorrent/idea/225 Surveyors should approve their answers]&lt;br /&gt;
**Custom Questions with tailoring, or the showAllResponsesExcept() function will let Surveyors see all of the questions and responses before clicking Submit. If the Navigation Menu option is enabled, it is easy to go back and correct answers.&lt;br /&gt;
*[http://ideas.limesurvey.org/ideatorrent/idea/1.92 Suppliment to #answernnXnnXnnn method of targetting form elements]&lt;br /&gt;
**You can now refer to questions and answers by their Question Code, so there is no longer a need to modify SGQA values.&lt;br /&gt;
*[http://ideas.limesurvey.org/ideatorrent/idea/262 More flexibility with hidden questions]&lt;br /&gt;
*[http://ideas.limesurvey.org/ideatorrent/idea/265 Remove specific conditions from multiple questions]&lt;br /&gt;
**You can now use Relevance, which is easier to manage than Conditions.  If  needed, they can all be exported from the database, edited in a spreadsheet, and re-imported.&lt;br /&gt;
*[http://ideas.limesurvey.org/ideatorrent/idea/268 Cross Survey Reporting]&lt;br /&gt;
**By using question codes that are unique across your surveys and versions, you can consolidate data from multiple surveys and/or compare them&lt;br /&gt;
*[http://ideas.limesurvey.org/ideatorrent/idea/275 Simplifying integration with other tools]&lt;br /&gt;
**Expression Manager uses Question Codes instead of SGQA, making it easier to integrate with other tools.&lt;br /&gt;
*[http://ideas.limesurvey.org/ideatorrent/idea/1.92 Expose assessment score to 3rd party app processing]&lt;br /&gt;
**This can be done with Equation question type&lt;br /&gt;
*[http://ideas.limesurvey.org/ideatorrent/idea/309 Multiple thank you pages]&lt;br /&gt;
**This can be supported via conditional relevance branching and tailoring&lt;br /&gt;
&lt;br /&gt;
=Additional Reading=&lt;br /&gt;
&lt;br /&gt;
==[[Expression Manager Sample Surveys|Expression Manager Sample Surveys]]==&lt;br /&gt;
&lt;br /&gt;
==[[Expression Manager HowTos|Use Cases and HowTos]]==&lt;br /&gt;
&lt;br /&gt;
==[[Expression Manager Examples|Step-by-Step Examples]].==&lt;br /&gt;
&lt;br /&gt;
==[[Expression Manager for developers|Reference for Developers]]==&lt;br /&gt;
&lt;br /&gt;
==[[Expression Manager Roadmap|RoadMap/Status/ToDo List]]==&lt;/div&gt;</summary>
		<author><name>Mdekker</name></author>
	</entry>
</feed>