The new PCIbex Farm is here! Be sure to check out all of its new features and changes.

Link Search Menu Expand Document

Collecting participant information

In this section, we’ll add a consent form and a section for participants to input their ID.


An Html element lets you insert an existing HTML document into a PennController experiment. This can be useful for displaying an informed consent form; instead of creating and printing many Text elements, you can print a single Html element.

We’ll use the mock consent form consent.html.

note

consent.html is only for illustrative purposes and is not a real consent form. You should follow your institution’s guidelines for informed consent.

The consent form has an checkbox that the participant should click to give consent. Make the checkbox an obligatory field by adding the "obligatory" class to the HTML <input> tag, as in <input type="checkbox" class="obligatory">. The "obligatory" class comes from the Ibex Form controller.

Text areas, text boxes, and radio buttons can also be made into obligatory fields. For more information on obligatory fields, read the Html element type documentation.

Some commands interact with obligatory fields, for example:

  • checkboxWarning: Defines (but does not print) an error message for an unfilled obligatory checkbox.
  • warn: Prints a defined error message for every unfilled obligatory field.
  • test.complete: Tests whether all obligatory fields have been filled out.

The test.complete command is a test command. Test commands have the prefix test., and test some aspect of the element they are called on. The success and failure keywords define a block of commands that are executed upon success or failure of the test, respectively:

PennController.ResetPrefix(null)

newTrial("TRIAL_LABEL",
    newX("ELEMENT_1", ...)
      .test.COMMAND_1()
      .success(...)
      .failure(...)
)

You can express the negation of a test by replacing the test. prefix with testNot., and you can use the keywords and and or to combine tests. For more information, read the Test commands documentation.

Test commands are used in two ways:

  • Within a trial to define conditional branching; or
  • Within a wait command to modify its success condition(s).

We’ll pass the test command test.complete as an argument to a wait command on a Button element.

Normally, if the wait command is called on a Button, experiment script execution pauses until the wait command’s success condition is fulfilled, in other words until the participant clicks the button. When a test command is passed as an argument, the wait command’s success condition is modified.

The test is run when the participant clicks the button, and experiment script execution is paused until the participant clicks the button and the test succeeds. If the participant clicks the button and the test fails, then experiment script execution remains paused. The test is run again the next time the participant clicks the button.

instructions

  • Create a new trial labeled "consent".
  • Modify the Sequence global command to include the "consent" trial.
  • Create and print an Html named "consent_form".
    1. Call the cssContainer command to set the container width to 720px.
    2. Call the checkboxWarning command to define an error message for an unfilled obligatory checkbox.
  • Create and print a centered Button named "continue".
    1. Call the wait command on the "continue" Button and pass the test.complete test command on the "consent_form" Html as an argument. This pauses experiment script execution until the participant clicks the button and all obligatory fields are filled out.
    2. Use the failure keyword on the test.complete command. If the consent checkbox is not filled out when the participant clicks the button, PennController calls the warn command on the "consent_form" Html, which prints the error message defined by the checkboxWarning command.

@// code omitted in the interest of space
@
@// Control trial sequence
!Sequence("consent", "instructions", randomize("experimental-trial"), "send", "completion_screen")
@
+// Consent form
+newTrial("consent",
+    newHtml("consent_form", "consent.html")
+        .cssContainer({"width":"720px"})
+        .checkboxWarning("You must consent before continuing.")
+        .print()
+    ,
+    newButton("continue", "Click to continue")
+        .center()
+        .print()
+        .wait(getHtml("consent_form").test.complete()
+                  .failure(getHtml("consent_form").warn())
+        )
+)
@
@// Instructions
@// code omitted in the interest of space

Recording participant IDs

A TextInput element creates a text input box that can collect participant input, like an ID number or experiment feedback.

We’ll ask participants to enter a name or ID number before they start the experiment, and use the log method to record the content of the TextInput as a new column in the results file.

However, you cannot directly pass the content of a TextInput as an argument to the log method. Create a Var element, make it a global variable, and set its value to the content of the TextInput. A global variable can be accessed in subsequent trial objects; a non-global variable can only be accessed in the trial that it’s created in. Then, you can pass the Var as an argument to the log method.

instructions

  • Update the instructions.
  • Create and print a TextInput named "input_ID" that is centered and has a 1em bottom margin.
  • Create a Var named "ID".
    • Call the global command to make it a global variable.
    • Call the set command to set its value to the content of the "input_ID" TextInput.
  • Use the log method on the "experimental-item" trial to record the participant ID.

@// code omitted in interest of space
@
@// Instructions
@newTrial("instructions",
@    defaultText
+        .cssContainer({"margin-bottom":"1em"})
@        .center()
@        .print()
@    ,
@    newText("instructions-1", "Welcome!")
@    ,
@    newText("instructions-2", "In this experiment, you will hear and read a sentence, and see two images.")
@    ,
@    newText("instructions-3", "<b>Select the image that better matches the sentence:</b>")
@    ,
@    newText("instructions-4", "Press the <b>F</b> key to select the image on the left.<br>Press the <b>J</b> key to select the image on the right.<br>You can also click on an image to select it.")
@    ,
@    newText("instructions-5", "If you do not select an image by the time the audio finishes playing,<br>the experiment will skip to the next sentence.")
+    ,
+    newText("instructions-6", "Please enter your ID and then click the button below to start the experiment.")
+    ,
+    newTextInput("input_ID")
+        .cssContainer({"margin-bottom":"1em"})
+        .center()
+        .print()
@    ,
@    newButton("wait", "Click to start the experiment")
@        .center()
@        .print()
@        .wait()
+    ,
+    newVar("ID")
+        .global()
+        .set(getTextInput("input_ID"))
@)
@
@// Experimental trial
*Template("items.csv", row => 
@    newTrial("experimental-trial",
@    // code omitted in interest of space
@    )
@    .log("group", row.group)
@    .log("item", row.item)
@    .log("condition", row.inflection)
+    .log("ID", getVar("ID"))
@)
@
@// code omitted in interest of space