Summary

This article covers adding commands to a script.

Table of Contents


Using Commands

At this point, you know how to start and end a script. You know how to get a script to execute. The next step is to start using commands to manipulate data, add forms, send emails or whatever is required by your application. This part of the tutorial will attempt to explain the thought process behind adding a command to a script.

The Command Reference

The command reference is the best and fastest way to determine what functions you need to perform a specific action. The command reference is provided in both alphabetical and categorical order. If you know what you are trying to do, one of these command listings should help you find the functions to do what you need to do.

Starting Point

We are going to build out one of the most common scripts so we will start with the base information that we already know:

<script scriptId="optional-set">
<body>

</body>
</script>

We have opened and closed the script and provided a body for the commands to reside in.

Adding Targets

We are building a script that looks to see if an answer is provided to a question. If the answer is not provided when that form is saved, we are going to alert the user that an answer must be provided for all of the target questions. So, we begin by listing out all of the targets that the specifications for our application list as required.

<script scriptId="optional-set">
    <body>

    </body>
    <target typeId="visitdtnscreen"/>
    <target typeId="brthdtc"/>
    <target typeId="sex"/>
    <target typeId="ethnic"/>
    <target typeId="race"/>
    <target typeId="compyn"/>
    <target typeId="deathdtn"/>
    <target typeId="deathcau"/>
</script>
Note: Targets do not have to be questions. Targets can also be forms, so that when the form is saved, the script will run. When the target is a question, the script will run when the question is saved during a form save.

As stated before, whenever any of these questions exist on a form, it will trigger the script to execute.

The “when” Target Attribute

There will be times when the designer does not want the script to be executed until the form has been completely and cleanly saved. There is a simple way to do this using the “when” attribute on the target.

The options for the “when” attribute is:

before (depreciated)
preprocess (replaced before)
after

An example is as follows:

<script scriptId="date_of_birth">
    <body>

    </body>
    <target typeId="visitdtnscreen" when="after" />
    <target typeId="brthdtc" when="after" />

</script>

In the above case, let’s assume that the script is setting the age based on the screening visit date and the birth date question. If the user were to enter a date with an incorrect format and the “when” attribute was set to “before” (the default), it would attempt to assign the age question with an incorrectly formatted date and it would cause an error. Since the “when” attribute is set to “after”, it will wait to run the script until the question/form is saved without opening any new alerts.

If the “when” attribute is set to “before”, it will attempt to run the script each time the question/form is saved.

Finding the Correct Command

In eClinical ™, edit checks/dependencies are also called alerts. So, we are going to go look in the command reference for a command that will allow us to trigger an alert on the eCRF. Looking under the boolean category, we find the alert command. The next step is to add the command to the script:

<script scriptId="optional-set">
    <body>
        <s:alert>

        </s:alert>
    </body>
    <target typeId="visitdtnscreen"/>
    <target typeId="brthdtc"/>
    <target typeId="sex"/>
    <target typeId="ethnic"/>
    <target typeId="race"/>
    <target typeId="compyn"/>
    <target typeId="deathdtn"/>
    <target typeId="deathcau"/>
</script>

One thing to note about all commands that are found in the command reference: when inserting them into a script, they must follow one of the two following formats:

<s:tag>

</s:tag>

OR

<s:tag/>

The first format will always require some additional parameter to evaluate that command. The second format will almost always have a parameter or attribute along with the command in the single line.

As stated previously, the command reference is broken down by category so that you should be able to find a command that will do what you need based on the output you are expecting from that command.

Command Parameters

If we look at the alert command that we’ve chosen for this script, we will see that it has multiple parameters.

expression
correction
text

Parameters are like commands to a command. They tell the command what input will be used and what expressions to execute to obtain the desired output. Each parameter performs a specific part of the function and most often will also take some sort of input.

<s:alert>
  <s:expression>
    <s:isSet/>
  </s:expression>
  <s:correction>
    <s:string value="optional"/>
  </s:correction>
  <s:text>
    <s:string value="An answer is missing and required.  Please verify."/>
  </s:text>
</s:alert>

In the above, the “expression” parameter simply takes another command (isSet). This expression could look at a number of things from the isSet command to see if a value is provided or not to something more complicated like a Regular Expression.

The “correction” parameter takes a string value that will always be either “optional” or “required”.

The “text” is the value that will be displayed to the user. This is provided using a string value as well.

All Together Now

The full script looks like the following:

<script scriptId="optional-set">
    <body>
        <s:alert>
            <s:expression>
                <s:isSet/>
            </s:expression>
            <s:correction>
                <s:string value="optional"/>
            </s:correction>
            <s:text>
                <s:string value="An answer is missing and required.  Please verify."/>
            </s:text>
        </s:alert>
    </body>
    <target typeId="visitdtnscreen"/>
    <target typeId="brthdtc"/>
    <target typeId="sex"/>
    <target typeId="ethnic"/>
    <target typeId="race"/>
    <target typeId="compyn"/>
    <target typeId="deathdtn"/>
    <target typeId="deathcau"/>
</script>

Command Paths (Script Paths) 

Finding Script Paths:

A majority of the commands in our system have parameters that require a script path in order to work. These parameters will require a ‘question path’, ‘form path’, ‘stringPath’, ‘datePath’, ‘numberPath’, or ‘partialDatePath’. The path used all depends on what the parameter supports.

Script paths are found by navigating to an eCRF within trial in the system and using a role that has the ‘Info Mode – Basic’ permission. This permission will give the ability to the ‘Show Info’ button at the top of the form and will provide path information for the form and questions on that form.

How to use Script Paths:

Script paths can be used in the following ways:

  1. Full paths
  2. Relative paths

Full paths are used when the referenced question in the command has a defined path. This means that the form is not a dynamic form and has a set location at all times (also known as a static form). For example, an age script needs programmed, and the result will be the difference between the date of birth and the screening visit date.

Age Calculation:

<script scriptId="assign_age">
    <body>
        <s:if>
            <s:and>
                <s:isSet>
                    <s:question>
                        <s:question path="/sub.dob"/>
                    </s:question>
                </s:isSet>
                <s:isSet>
                    <s:question>
                        <s:question path="/visit_scrV/sv_scrV.svdat"/>
                    </s:question>
                </s:isSet>
            </s:and>
            <s:assign>
                <s:question path="/visit_scrV/ic_scrV.age"/>
                <s:toString>
                    <s:dateDiff unit="year" method="integer" last="hour">
                        <s:from>
                            <s:datePath path="/sub.dob:value"/>
                        </s:from>
                        <s:to>
                            <s:datePath path="/visit_scrV/sv_scrV.svdat:value"/>
                        </s:to>
                    </s:dateDiff>
                </s:toString>
            </s:assign>
            <s:assign>
                <s:question path="/visit_scrV/ic_scrV.age"/>
                <s:string value=""/>
            </s:assign>
        </s:if>
    </body>
    <target typeId="svdat" action="update" when="after" shouldReconcile="true"/>
    <target typeId="dob" action="update" when="after" shouldReconcile="true"/>
</script>

Relative pathing allows the script to find the question relative to the target and does not require a defined path. This allows for a script to function across similar visits without having to design a script per visit. Relatives can be used in the following ways:


Example 1: Referring to questions on the current form (same as target)

To refer to a question on the current form, use one of these options:

  • .questionId
  • ./.questionId

Example (quality of life calculation):

<script scriptId='assign_qolScore' >
    <body>
        <s:if>
            <s:and>
                <s:isSet>
                    <s:question>
                        <s:question path='.qol01' type='question' />
                    </s:question>
                </s:isSet>
                <s:isSet>
                    <s:question>
                        <s:question path='.qol02' type='question' />
                    </s:question>
                </s:isSet>
                <s:isSet>
                    <s:question>
                        <s:question path='.qol03' type='question' />
                    </s:question>
                </s:isSet>
                <s:isSet>
                    <s:question>
                        <s:question path='.qol04' type='question' />
                    </s:question>
                </s:isSet>
                <s:isSet>
                    <s:question>
                        <s:question path='.qol05' type='question' />
                    </s:question>
                </s:isSet>
            </s:and>
            <s:assign>
                <s:question path='.qoltot' type='question' />
                <s:add operator='+' >
                    <s:numberPath path='.qol01:value' type='number' />
                    <s:numberPath path='.qol02:value' type='number' />
                    <s:numberPath path='.qol03:value' type='number' />
                    <s:numberPath path='.qol04:value' type='number' />
                    <s:numberPath path='.qol05:value' type='number' />
                </s:add>
            </s:assign>
            <s:assign>
                <s:question path='.qoltot' type='question' />
                <s:string value='' />
            </s:assign>
        </s:if>
    </body>
    <target action='update' shouldReconcile='true' typeId='qol01' when='preprocess' />
    <target action='update' shouldReconcile='true' typeId='qol02' when='preprocess' />
    <target action='update' shouldReconcile='true' typeId='qol03' when='preprocess' />
    <target action='update' shouldReconcile='true' typeId='qol04' when='preprocess' />
    <target action='update' shouldReconcile='true' typeId='qol05' when='preprocess' />
  </script>

Note: If defined script paths were used, it would require a script per visit since each question will have a different path per visit. Using relatives helps to reduce the number of scripts needed and save time programming. Lastly, using relatives will keep the script count down per form/question. Per best practices, there should only be 5 scripts per question and 20 scripts per form.

Example 2: Referring to a parent form or question on a parent form

  • To refer to a parent form, use ../
  • To refer to a question on a parent form, use ../.questionId

Example (form generation):

<script scriptId="create_fuv_dosForms">
    <body>
        <s:if>
            <s:and>
                <s:isSet>
                    <s:question>
                        <s:question path=".thtxdat"/>
                    </s:question>
                </s:isSet>
                <s:stringContains>
                    <s:stringPath path=".:alias" />
                    <s:string value="_fuv" />
                </s:stringContains>
            </s:and>
            <s:list>
                <s:createForm>
                    <s:parent>
                        <s:form path="../"/>
                    </s:parent>
                    <s:type>
                        <s:string value="dospretxb"/>
                    </s:type>
                    <s:alias>
                        <s:string value="dospretxb_fuv"/>
                    </s:alias>
                </s:createForm>
                <s:createForm>
                    <s:parent>
                        <s:form path="../"/>
                    </s:parent>
                    <s:type>
                        <s:string value="dospsttxb"/>
                    </s:type>
                    <s:alias>
                        <s:string value="dospsttxb_fuv"/>
                    </s:alias>
                </s:createForm>
            </s:list>
        </s:if>
    </body>
    <target action='update' shouldReconcile='true' typeId='thtx' when='after' />
  </script>

Note: ../ can be used multiple times (../../ etc...). Each usage will move the resolution up another level in the heirarchy. For example, ../../ will refer to the 'grandparent form' - the parent of the parent. 

Note: Relative path values (./, ./., ../, ../., ../../, etc...) use a notation that was not valid in any version before 14.6.0. If scripts programmed are valid and currently running before 14.6.0, they will continue to operate without any issues since the notation did not exist in previous versions. 


Need more help?

Please visit the Fountayn Contact Information page.