Global commands
Used outside of a trial.
table of contents
AddHost
syntax
AddHost()
description
You can use AddHost
to spare you from specifying a URL when you create an element with newAudio
, newVideo
or newImage
. The URL must end with /
.
example
click to expand
@
$AddHost("https://files.lab.florianschwarz.net/test/");
$AddHost("http://spellout.net/ibexfarm/static/images/");
@
@newTrial(
@ newImage("ibex", "ibex.jpg")
@ .print()
@ ,
@ newImage("wait", "https://openclipart.org/image/300px/svg_to_png/23920/Anonymous-Sandglass.png")
@ .print()
@ ,
@ newAudio("sentence", "test.mp3")
@ .play()
@ .wait()
@);
-
The trial shows two images and plays one audio file. PennController will first try send a request for the file https://files.lab.florianschwarz.net/test/ibex.png and another one for the file http://spellout.net/ibexfarm/static/images/ibex.png. The same is true for the audio file: PennController will first send a request for the file https://files.lab.florianschwarz.net/test/test.mp3 and another one for the file http://spellout.net/ibexfarm/static/images/test.mp3. PennController uses the resource from the first successfully resolving request: in this example, assuming there is a file named ibex.png at http://spellout.net/ibexfarm/static/images/ and a file named test.mp3 at https://files.lab.florianschwarz.net/test/ (and only there), those are the resources that PennController will use (it may still trigger warnings in the console for the unsuccessful requests). PennController will only look for the wait image at https://openclipart.org/image/300px/svg_to_png/23920/Anonymous-Sandglass.png, since a full URL is provided there.
AddTable
syntax
AddTable()
description
You can use this command to manually define a table to use with Template
. You normally do not need to use this command since, as of PennController beta 0.4, you can directly upload your CSV file under Resources / chunk_includes.
example
click to expand
@
$AddTable( "myTable", // Name of the table
$ "Type,Sentence\n"+ // Column names (mind the \n)
$ "practice,Hello world!\n"+ // First row (mind the \n)
$ "test,Bye world!" // Second row
$);
@
@Template( "myTable" , row =>
@ newTrial(
@ newText("type", row.Type)
@ .print()
@ ,
@ newButton("sentence", row.Sentence)
@ .print()
@ .wait()
@ )
@);
CheckPreloaded
syntax
CheckPreloaded()
description
PennController always starts the preloading of every image, audio and video resource used in your experiment as soon as the experiment starts running and, by default, it will wait before running a trial that all the resources it uses are preloaded. Since this could result in undesirable random breaks in the flow of your experiment, you can control when PennController should check that the resources used by (subsets of) your trials are preloaded before proceeding by using CheckPreloaded
.
example
click to expand
@
$CheckPreloaded("audio", "video");
@
@newTrial( "audio" ,
@ newAudio("audio file", "test.mp3")
@ .print()
@ .play()
@ .wait()
@);
@
@newTrial( "video" ,
@ newVideo("video file", "skate.mp4")
@ .print()
@ .play()
@ .wait()
@);
@
$CheckPreloaded();
@
@newTrial( "filler" ,
@ newImage("image", "square.png")
@ .print()
@ ,
@ newKey("fj", "FJ")
@ .wait()
@);
@
@newTrial( "test" ,
@ newImage("image", "triangle.png")
@ .print()
@ ,
@ newKey("fj", "FJ")
@ .wait()
@);
- Will make sure that test.mp3 and skate.mp4 are fully preloaded before running the very first PennController trial, labeled audio. After the PennController trial labeled video has ended, will make sure that all image, audio and video resources ever used in the experiment are preloaded before running the trial labeled filler (which practically means it will check that square.png and triangle.png are preloaded, since the first preloader made sure the audio and video resources were already preloaded).
Debug
syntax
Debug()
description
Runs your experiment in Debug mode.
example
click to expand
$PennController.Debug()
@
@PennController(
@ newButton("hello", "Hello world")
@ .print()
@ .wait()
@)
@
@PennController.AddTable( "Words" ,
@ "item,Word\n" +
@ "1,Hello\n" +
@ "2,World"
@)
@
@PennController.Template( "Words" ,
@ row => PennController(
@ newButton(row.Word)
@ .print()
@ .wait()
@ )
@)
DebugOff
syntax
DebugOff()
description
Tells your experiment to not run in Debug mode. This will close the popin window at the bottom-right corner of your experiment, no longer providing you with debugging tools and helpful feedback. You should only use this command when you are ready to collect data.
example
click to expand
$PennController.DebugOff()
@
@PennController(
@ newButton("hello", "Hello world")
@ .print()
@ .wait()
@)
@
@PennController.AddTable( "Words" ,
@ "item,Word\n" +
@ "1,Hello\n" +
@ "2,World"
@)
@
@PennController.Template( "Words" ,
@ row => PennController(
@ newButton(row.Word)
@ .print()
@ .wait()
@ )
@)
DownloadRecordingButton
EyeTrackerURL
syntax
EyeTrackerURL()
description
Tells the script where to send the data collected via the EyeTracker elements.
example
click to expand
@EyeTrackerURL("www.dummypage.com")
@newTrial( newButton("Start").print().wait(newEyeTracker().test.ready()) )
@
@newTrial(
@ newEyeTracker("tracker")
@ .calibrate(70)
@ .train(true)
@ ,
@ newButton("Click here first").print("20vw","40vh").wait().remove(),
@ newButton("Now Click here").print("60vw","40vh").wait().remove()
@ ,
@ newText("Left").css("padding","20vw").print("20vw", "40vh"),
@ newText("Right").css("padding","20vw").print("60vw", "40vh")
@ ,
@ getEyeTracker("tracker")
@ .stopTraining()
$ .add( getText("Left") , getText("Right") )
@ ,
@ newSelector().add( getText("Left") , getText("Right") ).wait()
@)
-
Collected data will be sent at the URL in the example.
-
Will add Left and Right as tracked elements.
Footer
GetTable().filter
syntax
GetTable().filter()
description
Returns a filtered version of the table, containing only rows whose specified column’s value is a match.
example
click to expand
@
@Template(
@ GetTable( "spreadsheet.csv" )
$ .filter( row => row.Item > 0 ) // 'Item' should be greater than 0, and
$ .filter( "ButtonText" , /second/ ) // 'ButtonText' should contain 'second'
@ ,
@ row => newTrial( "button trial" ,
@ newButton("test button", row.ButtonText)
@ .print()
@ .wait()
@ )
@ .log( "Item" , row.Item )
@ .log( "Text" , row.ButtonText )
@);
- Generates only one trial from a subset of the table spreadsheet.csv: first we only consider rows where the value in the Item column is a number greater than 0 (this is practically ineffective, for both rows in spreadsheet.csv already satisfy this condition) and we further consider only rows among those rows where the value of the ButtonText column is a text containing the string second (only the second row satisfies this condition).
GetTable().setGroupColumn
syntax
GetTable().setGroupColumn()
description
Tells which column in the table assigns each row to a given group of participants, i.e. which subset of rows PennController will keep for each group of participants listed in the column.
example
click to expand
@
@SetCounter();
@
@AddTable( "test_table" ,
@ "Spelling,Text\n"+
@ "Normal,Hello\n"+
@ "Reversed,olleH\n"+
@ "Normal,World\n"+
@ "Reversed,dlroW"
@);
@
@Template(
@ GetTable( "test_table" )
$ .setGroupColumn( "Spelling" )
@ ,
@ row => newTrial( "button trial" ,
@ newButton("the button", row.Text )
@ .print()
@ .wait()
@ )
@ .log( "Group" , row.Spelling )
@ .log( "Text" , row.Text )
@);
-
Creates a 2x4 table called test_table with column names Spelling and Text (manual creation for purpose of illustration—you would normally upload a CSV file to chunk_includes). Uses the column Spelling from this table to identify which rows go with which groups of participants.
-
Every other time the experiment is run, participants will see trials generated either from the two rows where Spelling is Normal or from the two rows where Spelling is Reversed.
-
The very first line runs a trial incrementing Ibex’s internal counter at the beginning of the experiment, which determines which group is run, so you can cycle through the rows if you re-run the experiment.
GetTable
syntax
GetTable()
description
Refers to a table, where tablename
can be the filename of a CSV file you uploaded to Resources (chunk_includes) or the name of a table that was created with AddTable
.
example
click to expand
@
$Template( GetTable( "spreadsheet.csv" ) , row =>
@ newTrial( "button trial" ,
@ newButton("test button", row.ButtonText)
@ .print()
@ .wait()
@ )
@ .log( "Group" , row.Item )
@ .log( "Text" , row.ButtonText )
@);
- Generate two trials from the table spreadsheet.csv which contains two rows and the columns Item and ButtonText.
GetURLParameter
syntax
GetURLParameter()
description
Retrieves the value of a parameter that was passed after ?
in the URL. This is particularly useful if you pass a uniquely identifying code to the URL when you recruit your participants, like http://spellout.net/ibexexps/PennController/Demo/experiment.html?id=abcdefgh
example
click to expand
@
@newTrial( "my trial" ,
@ newButton("helloworld", "Hello world!")
@ .log()
@ .print()
@ .wait()
@)
$.log( "ID" , GetURLParameter( "id" ) );
- Will add a column to each result line logged by my trial reporting the value that was passed after
id=
in the URL.
Header
syntax
Header()
description
Will evaluate and run sequenceOfCommands
at the beginning of each trial created with PennController
.
example
click to expand
@
$Header(
$ defaultText
$ .print()
$)
@
@newTrial(
@ newText("test sentence", "The cat is chasing the mouse")
@ ,
@ newText("instructions", "How natural is this sentence?")
@ ,
@ newScale("natural", 5)
@ .slider()
@ .before( newText("left", "Unnatural") )
@ .after( newText("right", "Natural") )
@ .print()
@ .wait()
@)
@
@newTrial(
@ newText("test sentence", "The mouse is being chased by the cat")
@ ,
@ newText("instructions", "How natural is this sentence?")
@ ,
@ newScale("natural", 5)
@ .slider()
@ .before( newText("left", "Unnatural") )
@ .after( newText("right", "Natural") )
@ .print()
@ .wait()
@)
-
Though no
print
command explicitly appears in the trials themselves, the Text elements will be printed onto the page because the header definesprint
as a default command for all Text elements.
InitiateRecorder
syntax
InitiateRecorder()
description
Use this to specify the URL of the PHP file to upload the audio recordings collected during the experiment.
example
click to expand
@
@Sequence("first_trial", "second-trial")
@
$InitiateRecorder(
$ "https://myserver/uploadVoices/saveRecordings.php"
$ ,
$ "This experiment collects audio recordings. **Once you grant it access to your recording device, you will be notified of whether you are being recorded by a label at the top of the page**"
$)
$.label("first-trial")
@
@newTrial( "second-trial" ,
@ newMediaRecorder("recorder", "audio")
@ .print()
@ .wait()
@)
- Adds a page asking for the participant’s authorization to use their recording device, using a custom text message.
PreloadZip
syntax
PreloadZip()
description
Instead of fetching audio and images from a distant URL for every single one of your PennController trials using one, you can choose to store them in ZIP archives that you upload on your server. Use PreloadZip
to tell where to look the ZIP archives up.
example
click to expand
- Click here for a detailed guide.
ResetPrefix
syntax
ResetPrefix()
description
By default, all the commands to create and refer back to elements in a PennController trial should be preceded by a prefix (PennController.Elements.
as of beta 0.3). It is standard practice that every command added by a javascript module (which is what PennController is) uses a specific prefix (in this case, PennController
). This is to avoid inadvertently overwriting (or being overwritten by) commands of the same names defined somewhere else, outside of the module. For instance, it could be that you or another module defined a function getImage
which, say, takes a filename and adds it at the end of a certain URL (this would be useful if you defined many items using built-in Ibex controllers that contain images and you do not want to type the host URL each time).
example
click to expand
@
@PennController.newTrial(
$ PennController.Elements.defaultImage
@ .size(80, 80)
@ ,
$ PennController.Elements.newText("helloworld", "Hello world!")
@ .print()
@ ,
$ PennController.Elements.newCanvas("geometry", 200, 100)
$ .add( 10, 10, PennController.Elements.newImage("left image", "triangle.png") )
$ .add( 110, 10, PennController.Elements.newImage("right image", "square.png") )
@ .print()
@ ,
$ PennController.Elements.newSelector("shapes")
$ .add( PennController.Elements.getImage("left image") , PennController.Elements.getImage("right image") )
@ .print()
@ .wait()
@);
-
Long, painful and a little messy, right?
-
Now if you already have a
getImage
function defined somewhere else and you do not want to rename it, but you do not want PennController to erase it either, you can choose to reset the prefix to make everything shorter while keeping your owngetImage
function. For instance, you can choose to use the prefixE
for Element (assuming no script defined a global object named E otherwise):
@
+PennController.ResetPrefix("E");
@
@E.newTrial(
$ E.defaultImage
@ .size(80, 80)
@ ,
$ E.newText("helloworld", "Hello world!")
@ .print()
@ ,
$ E.newCanvas("geometry", 200, 100)
$ .add( 10, 10, E.newImage("left image", "triangle.png") )
$ .add( 110, 10, E.newImage("right image", "square.png") )
@ .print()
@ ,
$ E.newSelector("shapes")
$ .add( E.getImage("left image") , E.getImage("right image") )
@ .print()
@ .wait()
@);
- This is already much better. But to the extent that PennController’s element commands have names that are not used by default Ibex projects, you may want to straight out drop the prefix using
PennController.ResetPrefix( null )
, which is what is assumed throughout this documentation (no longer assuming the pre-existence of a getImage function in your project).
SendResults
syntax
SendResults()
description
Since PennController 1.7, SendResults
can be used in three different environments:
example
click to expand
$Sequence( "hello" , "world" , SendResults() , "bye" )
@
@newTrial( "hello" ,
@ newButton("Hello")
@ .log()
@ .print()
@ .wait()
@)
@newTrial( "world" ,
@ newButton("Send quit now")
@ .callback(
@ getButton("World")
@ .remove()
@ ,
@ SendResults()
@ )
@ .print( 10 , 10 )
@ ,
@ newButton("World")
@ .log()
@ .print()
@ .wait()
@)
@
@newTrial( "bye" ,
@ newText("thanks", "Thank your for participating in this experiment.")
@ .print()
@ ,
@ newText("link", "Click here to confirm your participation.")
@ .print()
@ ,
@ newTimer("forever", 1)
@ .wait() // Timer never started: will wait forever
@)
@.setOption("countsForProgressBar",false)
- Through the Try-it interface, the Send quit now button will crash because the experiment is not run globally but instead from within the test page.
Sequence
syntax
Sequence()
description
Determines the order in which your trials will be run. Use your trials’ labels to manipulate the running order.
example
click to expand
$Sequence( "hello" , randomize("world") )
@
@newTrial( "world" ,
@ newButton("world", "Earth")
@ .print()
@ .wait()
@)
@newTrial( "world" ,
@ newButton("world", "Moon")
@ .print()
@ .wait()
@)
@newTrial( "world" ,
@ newButton("world", "Mars")
@ .print()
@ .wait()
@)
@
@newTrial( "hello" ,
@ newButton("world", "Hello...")
@ .print()
@ .wait()
@)
- Will run the trial labeled hello first, even though it is defined below the world ones, and then will run all three trials labeled world in a random order.
SetCounter
syntax
SetCounter()
description
Creates an item that will set Ibex’s internal counter when it is run.
example
click to expand
@AddTable( "myTable" ,
@ "Group,Button\n"+
@ "A,Hello\n"+
@ "B,World"
@);
@
@Sequence("counter", "trial");
@
$SetCounter("counter", "inc", 1);
@
@Template( "myTable" , row =>
@ newTrial( "trial" ,
@ newButton( "greetings" , row.Button )
@ .print()
@ .wait()
@ )
@);
- Increments the counter as soon as the experiment starts running. Since we use a table defining two groups (A and B) the button will read Hello or World every other time the experiment is run (try running it multiple times without clicking the button).
Template
syntax
Template()
description
Generates trials from a table. See this page to learn how to use it. You can have as many Template
as you want (which is helpful if you use different trial templates).
example
click to expand
@AddTable( "mytable" ,
@ "Type,Sentence,TargetPicture,CompetitorPicture\n"+
@ "Test,This is a square,square.png,triangle.png\n"+
@ "Filler,This is a triangle,triangle.png,pear.png"
@);
@
$Template( "mytable" , row =>
$ newTrial( row.Type ,
@ newText("sentence", row.Sentence)
@ .print()
@ ,
@ newSelector("choice")
@ ,
@ defaultImage
@ .size(200,200)
@ .selector("choice")
@ ,
@ newCanvas( "images", 500, 200 )
@ .add( 0, 0, newImage("target", row.TargetPicture) )
@ .add( 300, 0, newImage("target", row.CompetitorPicture) )
@ .print()
@ ,
@ getSelector("choice")
@ .shuffle()
@ .wait()
@ )
@);
- Generates trials labeled according to the Type column of the table, showing a sentence whose text is retrieved from the Sentence column of the table, and two pictures side by side retrieved from the TargetPicture and CompetitorPicture columns.
@AddTable( "mytable" ,
@ "Type,Sentence\n"+
@ "Filler,The cat that is chasing the mouse runs fast\n"+
@ "Test,The mouse that the cat is chasing runs fast"
@);
@
@Template( "mytable" , row =>
@ [
@ "DashedSentence", {s: row.Sentence},
$ "PennController", newTrial(
$ newText("question", "How natural did you find this sentence?")
@ .print()
@ ,
@ newScale("natural", 7)
@ .before( newText("left", "Completely unnatural") )
@ .after( newText("right", "Completely natural") )
@ .print()
@ .wait()
@ )
@ ]
@);
- Generates two-screen trials, the first screen using the native Ibex DashedSentence with the value from the Sentence column passed as its s parameter, the second screen using PennController to show a naturalness scale.
UploadRecordings
syntax
UploadRecordings()
description
Creates a trial which, when executed, will send the recordings collected so far via the MediaRecorder element to the URL provided to InitiateRecorder
.
example
click to expand
@Sequence(
@ "intro"
@ ,
@ sepWith("sendAsync", "recordTrial")
$)
@
@InitiateRecorder("https://my.server/path/to/uploadScript.php")
@ .label("intro")
@
$UploadRecordings("sendAsync", "noblock")
@
@newTrial("recordTrial",
@ newText("Please act out happiness").print()
@ ,
@ newMediaRecorder("happiness").print().log().wait()
@)
@
@newTrial("recordTrial",
@ newText("Please act out sadness").print()
@ ,
@ newMediaRecorder("happiness").print().log().wait()
@)
- Will start sending each video sample to the server immediately after it is recorded.
newTrial().label
syntax
newTrial().label()
description
This is another way to assign a label to a PennController trial so you can refer to it in Sequence
. It is most useful called on CheckPreloaded
or InitiateRecorder
since those commands do not take labels as arguments.
example
click to expand
@
$Sequence( "practice" , "preload-exp" , rshuffle("filler","test") )
@
@CheckPreloaded(
@ "filler"
@ ,
@ "test"
$).label( "preload-exp" )
- Creates a trial labeled preload-exp checking that all the resources used in the PennController trials labeled filler or test are preloaded, and refers to its label in
Sequence
so it will be run before the filler and test trials, but after the practice trials.
newTrial().log
syntax
newTrial().log()
description
You can use the .log
method to add columns to every line corresponding to this trial that is logged in the results file. You can add as many .log
as you want.
example
click to expand
@
@newTrial(
@ newButton("helloworld", "Hello world!")
@ .log()
@ .print()
@ .wait()
@)
$.log("Trial type", "One-Button")
$.log("Text on button", "Hello world!");
-
Will add One-Button and Hello world! to the end of every line saved to the results file for this trial.
newTrial().noFooter
newTrial().noHeader
syntax
newTrial().noHeader()
description
Will not run the header sequence at the beginning of the trial. Note that this also concerns default commands defined in the header: those will not be run in trials where you use noHeader
.
example
click to expand
@Header(
@ defaultButton
@ .print()
@ .wait()
@ ,
@ newText("please", "Please give a score")
@ .print()
@)
@
@newTrial( "twoClicks" ,
@ newScale("score", 5)
@ .print()
@ ,
@ newButton("validate", "Validate")
@ .wait( getScale("score").test.selected() )
@)
@
@newTrial( "oneClick" ,
@ newScale("score", 5)
@ .print()
@ ,
@ newButton("validate", "Validate")
@ .print()
@ .wait( getScale("score").test.selected() )
@)
$.noHeader()
-
The first trial (labeled twoClicks) will show a text at the top of the page, then a radio-button scale and a button. Because the header already contains a
wait
command, two clicks will be necessary to validate the button (the second one having to happen after a radio-button is selected). On the contrary, the second trial (labeled oneClick) which usesnoHeader
, will show no text at the top of the page and will only require one click on the button to validate it (assuming a radio-button is selected), because it will only evaluate and execute onewait
command.
newTrial().setOption
syntax
newTrial().setOption()
description
Lets you modify a parameter of the controller, as you would for any other controller in Ibex.
example
click to expand
@
@newTrial(
@ newScale("Score", 8)
@ .slider()
@ .print()
@ .wait()
@)
$.setOption("countsForProgressBar", false);
- This trial will not count for the progress bar at the top of the Ibex experiment page (see the Ibex documentation manual).
newTrial
syntax
newTrial()
description
The newTrial
command (formerly PennController
) creates a new PennController trial. You can use it in three environments: on its own to create a trial (since version 1.0), within Template
to generate trials from a spreadsheet, or within the definition of the Ibex variable items
to create single elements (deprecated since PennController 1.0).
example
click to expand
@
$newTrial(
@ newButton("helloworld", "Hello world!")
@ .print()
@ .wait()
@);
@
@Template( row =>
$ newTrial( row.Type ,
@ newButton("button", row.ButtonText)
@ .print()
@ .wait()
@ )
@);
- Creates one trial labeled unlabeled with a single button on the screen reading Hello world!, and generate one-button trials from a spreadsheet, assigning the text from its Type cells as their label and the text from its ButtonText cells as the button’s text (see
Template
).