Var element

Var elements (since beta 0.3)

let you manipulate variable values during run-time.

Creation:

newVar("myVar", 1000)

Note that the default value (1000 in the line just above) is the value to which the Var element is set at the very beginning of the experiment, when all newX commands are evaluated. If you pass something like Date.now(), it will always correspond to the timestamp of the beginning of the experiment. Use the command .set( v=>Date.now() ) instead if you want to set the value to the timestamp at the moment when the command is executed (see the example from .settings.local below).

Note also that if a Var element with the same name was made global before the current newVar command is executed, the current newVar command will refer back to that Var element instead of creating a new one, and the default value will be ignored (the global Var element will not be set to the default value). See the example from .settings.local below.

Example:

newVar("trialsLeft", 3)
,
newText("remain", " Number of remaining attempts: ")
    .settings.after( newText("trial", "3") )
,
newTextInput("guess", "Guess my name")
    .settings.after( getText("remain") )
    .print()
    .wait( 
      getTextInput("guess")
        .test.text( /Jeremy/i )
        .failure(              // Wrong guess:
          getVar("trialsLeft")
            .set( v => v-1 )   // Decrease trialsLeft 
          ,
          getText("trial")     // Update trial's text with it 
            .settings.text( getVar("trialsLeft") )
          ,
          getVar("trialsLeft") // Disable guess if 0 attempt left
            .test.is(0)
            .success( getTextInput("guess").settings.disable() )
        )   
    )

The code above creates a new Var element named trialsLeft and initiates it with the value 3. It then adds a text input box to the page pre-filled with Guess my name, and followed by Number of remaining attempts: 3 to its right.
When the return/enter key is pressed while editing the text input box, the code tests whether its content is Jeremy (ignoring case). If the content of the text input box is not a match, trialsLeft is decreased by 1 and the text is updated. Additionally, if 0 was reached, the text input box is disabled, thus preventing further proceeding.

Actions

var.set

getVar(id).set( value ) (since beta 0.3)

or getVar(id).set( function )

Sets the Var element to the specified value.

You can pass a function as value, which takes the current value of the Var element as an argument and should return the new value to which it will be updated.

Example:

defaultText
    .print()
,
defaultKey
    .wait()
,
newVar("firstKeyPressed")
,
newText("firstPress", "Press any key")
,
newKey("firstKey", "")
,
getVar("firstKeyPressed")
    .set( getKey("firstKey") )
,
newText("printFirstKey", "")
    .settings.text( getVar("firstKeyPressed") )
,
newText("secondPress", "Good, now press a second key.")
,
newKey("secondKey", "")
    .test.pressed( getVar("firstKeyPressed") )
    .success( newText("same", "So, you pressed the same key twice!") )
    .failure( newText("diff", "You appear to be quite inconstant.") )
,
newButton("validate", "OK")
    .print()
    .wait()

First creates a Var element named firstKeyPressed and then prints a text inviting to press any key. When a key is pressed, it is stored in the Var element (.set command). The Var element is then used to print which key was pressed, and when a second key is pressed, it is used to test that the same key was pressed.

standard.setVar

getElement(id).setVar( varName ) (since beta 0.3)

Stores the current value of the element in the Var element named varName (if it exists).

What the current value corresponds to is specific to each element type:

  • For Audio elements, it corresponds to the timestamp of the end of the last playback so far (0 if never played back or playback never eneded).
  • For Button elements, it corresponds to the timestamp of the last click so far (0 if never clicked).
  • For Canvas elements, it corresponds to the number of elements it currently contains.
  • For Function elements, it corresponds to the value returned by the function.
  • For Html elements, it corresponds to whether the element is completely filled.
  • For Image elements, it corresponds to whether the image is currently being displayed.
  • For Key elements, it corresponds to the last key that was pressed so far (empty string if no key has been pressed so far).
  • For Scale elements, it corresponds to the value of the last option that was selected (NaN if no option has been selected so far).
  • For Selector elements, it corresponds to the last element that was selected (null if no element has been selected so far).
  • For Text elements, it corresponds to the current text.
  • For TextInput elements, it corresponds to the text that is currently in the input box.
  • For Timer elements, it corresponds to whether the timer has elapsed.
  • For Tooltip elements, it corresponds to whether the tooltip has been validated.
  • For Var elements, it corresponds to the element’s value.
  • For Video elements, it corresponds to the timestamp of the end of the last playback so far (0 if never played back or playback never eneded).
  • For VoiceRecorder elements, it corresponds to the last recording (undefined if no recording so far).
  • For Youtube elements, it corresponds to whether the video has been played.

Example:

newVar("name")
,
newTextInput("nameInput", "What is your name?")
    .settings.once()
    .print()
    .wait()
    .setVar("name")
,
newText("helloname")
    .settings.before( newText("hello", "Hello ") )
    .settings.text( getVar("name") )
    .print()

Creates a Var element named name and adds a text box in which to enter a name. When the return/enter key is pressed while editing the input box, it disables the box and stores its value in the Var element named name. Then it prints a text reading Hello name, where name corresponds to the value of the Var element.

Settings

var.settings.global

getVar(id).settings.global() (since beta 0.3)

Makes the Var element accessible from the script that has not been evaluated yet (=~ all the script below .settings.global()).

Note: any newVar command using the same id will be ignored if it comes further below the .global() setting command. This is particularly helpful when calling newVar in the Header, the Footer or within Template: the value of the global Var element will not be reset with each new trial

Example:

PennController(
    newVar("participantsName", "")
        .settings.global()
    ,
    newTextInput("name", "Please write your name")
        .print()
        .wait()
        .setVar( "participantsName" )
)
.log("Participant", getVar("participantsName") );

PennController(
    newText("hello", "How are you today ")
        .settings.after( newText("name", "").settings.text(getVar("participantsName")) )
        .print()
    ,
    newButton("good", "Good, thank you")
        .settings.after( newButton("bad", "Not so well") )
        .print()
    ,
    newSelector("mood")
        .settings.add( getButton("good"), getButton("bad") ) 
        .wait()
)
.log("Participant", getVar("participantsName") );

The code above creates two PennController trials: the first one creates a global Var element named participantsName whose value is set to the text contained in the TextInput element at the end of the trial; the second trial prints a Text element reading “How are you today “ and appends another Text element to its right, whose content is set to the value of the global Var element.

var.settings.local

getVar(id).settings.local() (since beta 0.3)

Makes the Var element accessible only from the script of the current PennController instance (default setting). If a Var element with the same named was made global before (using .settings.global()—see above) then the Var element reverts to being local (while keeping its current value), meaning that any further Var element with the same name will no longer share the value of the preceding same-named Var elements.

Local Var elements you define in the Header or in the Footer are local to each PennController trial: changing their value in one trial will not affect their value in subsequent trials.

The example below is complex, because you normally would not need to use the local settings command. We are considering a situation where we want to make the Var element global only temporarily.

Example:

PennController.Header(
    newVar("StartTime", 0)
        .test.is( 0 )       // Won't be 0 if set as global
        .success(           // 0 means local: set time
            getVar("StartTime")
                .set( v=>Date.now() )
        )
);

PennController.Footer(
    newVar("TimeDifference")
        .set( getVar("StartTime") )
        .set( v=>Date.now()-v )
    ,
    newText("elapsed")
        .settings.text( getVar("TimeDifference") )
        .settings.before( newText("labelElapsed", "Time elapsed (in ms): ") )
        .print()
    ,
    newButton("validate", "Continue")
        .print()
        .wait()
);


PennController( "label" ,
    getVar("StartTime")
        .settings.global()  // Make global on 1st trial
    ,
    newButton("getTimeDiff", "How many ms since display?")
        .print()
        .wait()
);

PennController( "label" ,
    getVar("StartTime")
        .settings.local()  // Make local again on 2nd trial
    ,
    newButton("getTimeDiff", "How many ms since PREVIOUS display?")
        .print()
        .wait()
);

PennController( "label" , // Var is local: 0 => set time (header)
    newButton("getTimeDiff", "How many ms since NEW display?")
        .print()
        .wait()
);

The Header creates a new Var element named StartTime initially set to 0, if no Var element named StartTime was previously made global. When the first of the three label trials is run, there is no global StartTime yet, and the test from the Header is successful: StartTime is set to the current timestamp. The script for the first label trial is then executed: StartTime is made global, and a button is added to the page. When the button is clicked, the Footer creates a new Var element named TimeDifference which is first set to the value of StartTime and then set to the current timestamp subtracted of StartTime. The result is displayed in a new Text element and a button to be clicked for proceeding is added to the page.

When the second label trial is run, the StartTime element is global, so its value remains unchanged from the previous trial: the Header practically has no effect. Then the script of the second trial is executed and StartTime is made local again (keeping its current value for the remaining of the trial though). At the end of the trial, since StartTime still has the value set on the first trial, the reported time difference corresponds to how many milliseconds elapsed since the display of the first trial.

When the third label trial is run, the Header creates a new Var element named StartTime, initially set to 0: indeed, trial #2 made StartTime local again, and so when the newVar command from the Header is executed on trial #3, it ‘sees’ no existing Var element named StartTime. The test is therefore successful and StartTime is set to the current timestamp. The rest of the trial proceeds as in trial #1.

var.settings.log

getVar(id).settings.log() (since beta 0.4)

or getVar(id).settings.log("final")

or getVar(id).settings.log("set")

Adds a line to the results file indicating the value of the Var element.

Blank of "final" are equivalent and will add a line reporting the value of the Var element at the end of the trial. Passing "set" will add a line for each .set command that was called during runtime and report the value to which the command set the Var element.

Example:

newVar("image", "none")
    .settings.log("final", "set")
,
newText("instructions", "Press any key")
    .print()
,
newKey("any", "")
    .wait()
,
getKey("any")
    .test.pressed(" ")
    .success(
        newImage("tree", "Tree.png")
            .print()
        ,
        getVar("image")
            .set( "tree" )
    )
,
getButton("continue", "Continue")
    .print()
    .wait()

Adds a line of text reading Press any key and wait for any key to be pressed. Adds an image of a tree if the space key was pressed. Adds a button to click to continue.

At least one line will be added to the results file, indicating the final value of the Var element (either none or tree, depending on whether the pressed key was the space key). If the space key was pressed, another line will be added, reporting the value and the timestamp corresponding to the .set command (and to the key press, since .set is executed immediately after it).

Tests

var.test.is

getVar(id).test.is( value ) (since beta 0.3)

or getVar(id).test.is( function )

Tests the value of the Var element. You can pass a function which takes the element’s value as its argument and returns true or false.

Example:

newVar("trialsLeft", 3)
,
newText("remain", " Number of remaining attempts: ")
    .settings.after( newText("trial", "3") )
,
newTextInput("guess", "Guess my name")
    .settings.after( getText("remain") )
    .print()
    .wait( 
      getTextInput("guess")
        .test.text( /Jeremy/i )
        .failure(              // Wrong guess:
          getVar("trialsLeft")
            .set( v => v-1 )   // Decrease trialsLeft 
          ,
          getText("trial")     // Update trial's text with it 
            .settings.text( getVar("trialsLeft") )
          ,
          getVar("trialsLeft") // Disable guess if 0 attempt left
            .test.is(0)
            .success( getTextInput("guess").settings.disable() )
        )   
    )