Scale element

Scale elements let you add one-line multi-button scales to the screen. The buttons can be radio buttons or text buttons. Only one button in the line can be selected at a time.

Creation:

newScale("id", 5)

or newScale("id", "left button", " middle button", "right button")

Example:

newScale("hunger", 5)
    .settings.before( newText("left", "Right now, I am... very hungry ") )
    .settings.after( newText("right", " not hungry at all") )
    .print()
    .wait()

The code above adds a 5-point radio scale to the screen, preceded by the text Right now, I am… very hungry to its left, and followed by the text not hungry at all to its right, and waits for a click on one of its buttons.

Actions

scale.select

getScale(id).select(option)

or getScale(id).select(index)

or getScale(id).select(option, "log")

Selects the specified option on the scale.

If you pass a second argument (e.g. “log”) then the selection will be treated as if it were a manual selection, and will be recorded in the results file if you called log.

Example:

newText("What programming language is PennController based on?")
    .print()
,
newScale("answer",  "C++", "JavaScript", "Python", "R")
    .settings.labelsPosition("right")
    .print()
,
newButton("Check my answer")
    .print()
    .wait( getScale("answer").test.selected() )
,
getScale("answer")
    .test.selected("JavaScript")
    .success(
        newText("Good job!")
            .print()
    )
    .failure(
        newText("Wrong...")
            .print()
    )
,
getScale("answer")
    .select("JavaScript")
    .settings.disable()

Adds a question, a scale with four options and a button onto the page, then waits until the button is clicked while an option is selected. Once the button is clicked, prints a different feedback message depending on whether JavaScript is selected, then selects the JavaScript option (the correct answer) and disables the scale.

scale.wait

getScale(id).wait()

or getScale(id).wait("first")

or getScale(id).wait(test)

Waits until one of the buttons is clicked before evaluating and executing the next commands.

If you call wait("first"), then if a button is already selected when this command is evaluated, the next commands are evaluated and executed right away. If no button in the scale was clicked before, the next commands are only evaluated and executed after a button is clicked.

If you pass a test on an element as an argument, it only evaluates and executes the next commands when a button is clicked while the test is successful. If the test is not successful, it will be checked again upon the next click.

newScale("hunger", 5)
    .settings.before( newText("left", "Right now, I am... very hungry ") )
    .settings.after( newText("right", " not hungry at all") )
    .print()
    .wait()

Adds a 5-point radio scale to the screen and waits for a click on one of its buttons.

standard.print

getElement(id).print()

or getElement(id).print(x,y) (limited support in PennController 1.3, general since 1.4)

or getElement(id).print(x,y,canvas) (limited support in PennController 1.3, general since 1.4)

Adds the content of the element to the screen. This has no effect for non-visual elements such as the purely interactive Selector elements.

Since PennController 1.3, you can pass x and y values to print the element at a specific position on the page, or on a Canvas element if you pass one (or the name of a Canvas element) as the third parameter. You can use any CSS coordinate format for x and y, or special string values following the respective formats "left|center|right at ..." and "top|middle|bottom at ...". Note that x and y are not supported for Audio, Canvas, Scale, TextInput, Video and Youtube elements in PennController 1.3 ; note also that elements added with .settings.before and .settings.after mess with proportional coordinates.

standard.refresh

getElement(id).refresh() (since PennController 1.1)

Calls the command print again on the element, while leaving it where it was printed last.

This command is primarily useful if some aesthetic command does not take effect unless print is called afterward, but you do not want to call print because calling it when you need the aesthetic command to take effect would move the element undesirably.

NOTE: PennController 1.1 handles this command incorrectly and it bugs systematically (draft)

Example:

newImage( "smiley" , "ya.png" )
,
newCanvas( "myCanvas" , 100 , 100 )
    .settings.css( "border" , "solid 1px black" )
    .settings.center()
    .settings.add( "center at 50%" , "center at 50%" , getImage("smiley") )
    .print()
,
newButton( "resize" , "Resize the image" )
    .print()
    .wait()
,
getImage( "smiley" )
    .settings.size( 64, 64 )
,
getCanvas("myCanvas")
    .refresh()

Prints the smiley image at the center of the canvas and adds a button below the canvas. After the button is clicked, the smiley is resized to 64×64 and without refresh the smiley would no longer be centrally aligned on canvas. Calling print on the canvas would recenter the image correctly, but it would move the canvas below the button. The solution is therefore to call refresh (or to call the settings command add again on the canvas).

standard.remove

getElement(id).remove()

Removes the element from the screen. This has no effect for non-visual elements such as the purely interactive Selector elements.

Note that this leaves no space where the element previously was on the page (this is really removing the element, not just hiding it).

Example

newButton("clickme", "Click me")
    .print()
    .wait()
    .remove()

Adds a button that says Click me to the screen, and removes it after it is clicked.

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

scale.settings.button

getScale(id).settings.button()

Makes the buttons of the scale appear as clickable text buttons that are framed when selected. If you passed a number when creating the scale, the buttons will be labeled with numbers (starting from 0).

Example:

newScale("score", 6)
    .settings.button()
    .settings.before( newText("score label", "Score: ") )
    .settings.after( newText("score text", " / 5") )
    .print()
    .wait()

Adds a scale with 6 horizontally aligned buttons to the screen, labeled from 0 to 5, and waits for a click on one of them.

scale.settings.callback

getScale(id).settings.callback( sequenceOfCommands ) (since beta 0.4)

Executes a sequence of commands whenever a choice is made on the scale. This is particularly useful if, for example, you want to reveal a TextInput element only when a certain option is chosen.

Example:

newTextInput( "other" , "" )
    .settings.hidden()
,
newScale("yarrel",  "Yanny", "Laurel", "other")
    .settings.labelsPosition( "right" )
    .settings.after( getTextInput("other") )
    .settings.callback(
        getScale("yarrel")
            .test.selected( "other" )
            .success( getTextInput("other").settings.visible() )
            .failure( getTextInput("other").settings.hidden()  )
    )
    .print()

scale.settings.default

getScale(id).settings.default( value ) (since beta 0.3)

Makes a value selected by default when printing the scale element. You can pass either an index or a text value as value.

Note that sliders necessarily have a default value. If you do not use .settings.default to specify one, the central one will be used (or next to central if the number of possible values is odd).

Example:

newScale("score",   "Terrible", "Bad", "Good", "Terrific")
    .settings.before( newText("left", "The last movie I saw was ") )
    .settings.labelsPosition("top")
    .settings.default("Terrific")
    .print()

Adds a scale with 4 horizontally aligned radio buttons to the screen, with their respective labels appear on top of them, selects the right-most button by default, and waits for a click on a radio button.

scale.settings.horizontal

getScale(id).settings.horizontal() (since beta 0.3)

Makes the buttons and labels of the scale appear horizontally. This is the default aesthetics of scales.

Note: until version 1.0, you need to call print (again) for the settings to take effect.

Example:

newScale("slider",   100)
    .settings.slider()
    .settings.vertical()
    .print()
,
newButton("rotate", "Horizontal slider")
    .print()
    .wait()
,
getScale("slider")
    .settings.horizontal()
    .print()

Adds a vertical slider to the page and a button which, when clicked, rotates the slider so it appears horizontally.

scale.settings.keys

getScale(id).settings.keys( "key1", "key2", ... )

or getScale(id).settings.keys()

Respectively associates the scale’s options with the specified keys for selection.

If you pass no argument, will check whether your scale’s options are all single characters and, if so, will use them as keys. If not, will respectively associate the scale’s options with the numeric keys.

Example:

newScale("grade",  "A", "B", "C", "D", "E", "F")
    .settings.labelsPosition("top")
    .settings.keys()
    .print()
,
newScale(9)
    .settings.before( newText("Confidence:") )
    .settings.keys()
    .print()
,
newScale("role",  "TA", "Professor")
    .settings.labelsPosition("right")
    .settings.keys("T", "P")
    .print()

Will add three scales onto the screen. Pressing A, B, C, D, E or F will select an option on the first scale, pressing a numeric key from 1 to 9 will select an option on the second scale, and pressing T or P will select an option on the third scale.

scale.settings.labels

Deprecated since version 1.0. Use the settings command labelsPosition instead.

scale.settings.labelsPosition

(Since version 1.0, formerly labels)

getScale(id).settings.labelsPosition("bottom")

or getScale(id).settings.labelsPosition("left")

(since version 1.0)

or getScale(id).settings.labelsPosition("top")

or getScale(id).settings.labelsPosition("right")

(since version 1.0)

Sets the position of the labels of the scale to bottom, left, top or right. If you did not specify labels, the buttons’ indices will be used instead.

newScale("score",  "Bad", "So-so", "Good")
    .settings.radio()
    .settings.labelsPosition("right")
    .settings.before( newText("label", "Score: ") )
    .settings.center()
    .print()
    .wait()

Adds a scale with 3 horizontally aligned radio buttons to the screen, with labels Bad, So-so and Good above their respective buttons, and waits for a click on one of them.

scale.settings.log

getScale(id).settings.log()

or getScale(id).settings.log("last") (since beta 0.4)

or getScale(id).settings.log("first") (since beta 0.4)

or getScale(id).settings.log("all")

Adds a line to the result file indicating which button is selected at what time(stamp).

Leaving the parentheses blank is equivalent to passing only "last": only the very last option to be selected will be saved. If "first", then the very first option to be selected will be saved. If "all", a line will be added for each selection on the scale.

Note: in beta 0.3, blank and "all" were equivalent and were the only available options.

Example:

newScale("hunger", 5)
    .settings.before( newText("left", "Right now, I am... very hungry ") )
    .settings.after( newText("right", " not hungry at all") )
    .settings.log("first", "last")
    .print()
    .wait()
,
newButton("validation", "Validate")
    .print()
    .wait()

Adds a 5-point radio scale and waits for a click on one of its buttons before adding a button to the screen. Only the very first and the very last clicks on the scale will be saved in the results file (if only one selection happened, only one line will be added).

scale.settings.once

getScale(id).settings.once()

Disables the scale after the first selection has happened.

newScale("hunger", 5)
    .settings.before( newText("left", "Right now, I am... very hungry ") )
    .settings.after( newText("right", " not hungry at all") )
    .settings.once()
    .print()
    .wait()

Adds a 5-point radio scale and waits for a click on one of its buttons, after which selection cannot be changed and a button appears below the scale.

scale.settings.radio

getScale(id).settings.radio()

Makes the buttons of the scales appear as radio buttons.

Example:

newScale("score",   "Terrible", "Bad", "Good", "Terrific")
    .settings.before( newText("left", "The last movie I saw was ") )
    .settings.radio()
    .settings.labelsPosition("top")
    .print()
    .wait()

Adds a scale with 4 horizontally aligned radio buttons to the screen, with their respective labels appear on top of them, and waits for a click on a button.

scale.settings.slider

getScale(id).settings.slider() (since beta 0.3)

Transforms the scale into a slider. Note that sliders always have a default value in order to place their cursor. If you do not use settings command default, the central (or next-to-central) value will be used.

The Comments column of the results line will report the duration of moving the slider (in ms).

Example:

newScale("slider",   100)
    .settings.slider()
    .print()

Adds a 100-point slider to the page and a validation button.

scale.settings.vertical

getScale(id).settings.vertical() (since beta 0.3)

Makes the buttons and labels of the scale appear vertically, with the initially left-most value to the bottom and the initially right-most value on top.

If you also use .settings.labelsPosition, top labels will accordingly appear on the right, and bottom labels will appear on the left.

Example:

newScale("slider",   100)
    .settings.slider()
    .settings.vertical()
    .print()

Adds a 100-point vertical slider to the page and a button to validate.

standard.settings.after

getElement(id).settings.after( getElement(id) )

Adds some content to the right of the element.

Example:

newImage("bad", "no.png")
,
newImage("good", "ya.png")
,
newText("left label", "Bad")
    .settings.before( getImage("bad") )
,
newText("right label", "Good")
    .settings.after( getImage("good") )
,
newScale("judgment", 5)
    .settings.before( getText("left label") )
    .settings.after( getText("right label") )
    .print()
    .wait()

Creates two image and two text elements and prints a 5-point radio-button scale, with the text Bad preceded by the image no.png on its left, and the text Good followed by the image ya.png on its right.

standard.settings.before

or getElement(id).settings.before( getElement(id) )

Adds some content to the left of the element.

Example:

newImage("bad", "no.png")
,
newImage("good", "ya.png")
,
newText("left label", "Bad")
    .settings.before( getImage("bad") )
,
newText("right label", "Good")
    .settings.after( getImage("good") )
,
newScale("judgment", 5)
    .settings.before( getText("left label") )
    .settings.after( getText("right label") )
    .print()
    .wait()

Creates two image and two text elements and prints a 5-point radio-button scale, with the text Bad preceded by the image no.png on its left, and the text Good followed by the image ya.png on its right.

standard.settings.bold

getElement(id).settings.bold()

Makes any text in the element appear boldfaced.

Example:

newText("warnning", "NOTE: this text is a warning!")
    .settings.bold()
    .settings.italic()
    .settings.color("red")
    .print()

Prints a text in boldface, italic and red.

standard.settings.center

getElement(id).settings.center()

Makes the element appear centered on the horizontal axis.

Example:

newText("helloworld", "Hello world")
    .settings.center()
    .print()

Prints Hello world onto the screen, horizontally centered.

standard.settings.color

getElement(id).settings.color("color")

Makes any text in the element appear in the specified color. The "color" string follows CSS conventions (most common names such as “red”, “blue”, … are valid)

Note: if you want to change the background color of an element (say, a Canvas element) use .settings.css("background", color) where color is the name of a color (e.g. "green")

Example:

newText("warnning", "NOTE: this text is a warning!")
    .settings.bold()
    .settings.italic()
    .settings.color("red")
    .print()

Prints a text in boldface, italic and red.

standard.settings.css

getElement(id).settings.css("styleName", "style")

or getElement(id).settings.css({"style name 1": "style 1", "style name 2": "style 2"})

Applies the CSS style(s) to the element.

Example:

newText("frame", "framed")
    .settings.css("border", "solid 1px black")
,
newText("sentence", "The last word of this sentence is ")
    .settings.after( getText("frame") )
    .print()

Prints a text reading The last word of this sentence is framed, with the last word (framed) framed in a box with 1px black borders.

standard.settings.disable

getElement(id).settings.disable()

Disables any interactive feature of the element.

Note: this does not prevent an element that is part of a Selector element from being selected.

Example:

newAudio("sentence", "test.mp3")
    .print()
    .wait()
,
getAudio("sentence")
    .settings.disable()

Prints buttons to play/pause the audio file test_sentence.ogg, and disables those buttons when the file has played through.

standard.settings.enable

getElement(id).settings.enable()

Enables any interactive feature of the element that was previously disabled.

Example:

newAudio("sentence", "test.mp3")
    .settings.once()
    .print()
,
newKey("secret key", "R")
    .wait()
,
getAudio("sentence")
    .settings.enable()

Prints buttons to play/pause the audio file test_sentence.ogg, and disables those buttons when the file has played through (see audio.settings.once).

standard.settings.hidden

getElement(id).settings.hidden() (since beta 0.3)

Makes the element invisible. Note that when printed, a hidden element still occupies space on the page, but its content is not visible.

Example:

newText("instruction", "Guess what fruit is in the image below")
    .print()
,
newImage("fruit", "pear.png")
    .settings.hidden()
    .print()
,
newButton("reveal", "Reveal fruit")
    .print()
    .wait()
,
getImage("fruit")
    .settings.visible()

Adds some text to the page, a blank space below it and a button below the blank space which, when clicked, reveals an image of a pear.

standard.settings.italic

getElement(id).settings.italic()

Makes any text in the element appear in italic.

Example:

newText("warnning", "NOTE: this text is a warning!")
    .settings.bold()
    .settings.italic()
    .settings.color("red")
    .print()

Prints a text in boldface, italic and red.

standard.settings.left

getElement(id).settings.left()

Makes the element appear horizontally aligned to the left (default).

Note: the left means the left of the container of the element, not necessarily the left of the screen.

Example:

newText("helloworld", "Hello world")
    .settings.right()
    .print()
,
newButton("left", "Align text to the left")
    .print()
    .wait()
,
getText("helloworld")
    .settings.left()

Prints Hello world onto the screen, horizontally aligned to the left.

standard.settings.right

getElement(id).settings.right()

Makes the element appear horizontally aligned to the right.

Note: the right means the right of the container of the element, not necessarily the right of the screen.

Example:

newText("sentence", "This is a longer sentence")
    .print()
,
newText("helloworld", "Hello world")
    .settings.right()
    .print()

Prints Hello world onto the screen, horizontally aligned to the right.

standard.settings.selector

getElement(id).settings.selector( selectorName )

or getElement(id).settings.selector( getSelector(selectorName) ) (since beta 0.3)

Since beta 0.3, Selector adds a .settings.selector command to all elements as another method for adding them to a selector.

Example:

newSelector("shapes")
,
newImage("square", "square.png")
    .settings.selector("shapes")
,
newImage("triangle", "triangle.png")
    .settings.selector("shapes")
,
newCanvas("shapes canvas", 825, 400)
    .settings.add(  0, 0, getImage("square") )
    .settings.add(425, 0, getImage("triangle") )
    .print()
,
getSelector("shapes")
    .wait()

Adds two images side by side and waits for a click on either one of them.

standard.settings.size

getElement(id).settings.size(width, height)

Resizes the element to a width of width pixels and a height of height pixels.

Example:

newImage("smiley", "pear.png")
    .settings.size(40, 40)
    .print()

Adds a 40x40px image pear.png onto the screen.

standard.settings.visible

getElement(id).settings.visible() (since beta 0.3)

Makes the element visible (again). This is useful if you previously hid the element with .settings.hidden.

Example:

newText("instruction", "Guess what fruit is in the image below")
    .print()
,
newImage("fruit", "pear.png")
    .settings.hidden()
    .print()
,
newButton("reveal", "Reveal fruit")
    .print()
    .wait()
,
getImage("fruit")
    .settings.visible()

Adds some text to the page, a blank space below it and a button below the blank space which, when clicked, reveals an image of a pear.

Tests

scale.test.selected

getScale(id).test.selected()

or getScale(id).test.selected( value )

Tests whether a button is selected.

If you pass a value, it will check that it matches the label of the selected button if it has a label, its index otherwise. If you do not pass a value, it simply checks that a selection happened.

Example:

newScale("score",   5)
    .settings.before( newText("label", "Score: ") )
    .print()
,
newButton("validation", "Validate")
    .print()
    .wait( getScale("score").test.selected() )

Adds a 5-point radio-button scale and a Validate button to the screen. Clicking on the Validate button is successful only when a radio button is selected.

standard.test.printed

getElement(id).test.printed() (since beta 0.3)

Tests whether the element was printed onto the page (and has not been removed since then).

Example:

newText("instructions", "Click on Top/Bottom to NOT print its word")
    .print()
,
newButton("top", "Top")
    .settings.callback( getButton("top").remove() ) 
    .print()
,
newButton("bottom", "Bottom")
    .settings.callback( getButton("bottom").remove() )
    .print()
,
newButton("print", "Print the buttons' words")
    .print()
    .wait()
    .remove()
,
getButton("top")
    .test.printed()
    .success( newText("top word", "hello").print() )
,
getButton("bottom")
    .test.printed()
    .success( newText("bottom word", "world").print() )

Prints a Top and a Bottom button onto the page, which disappear when clicked. After a click on the print button, the word hello will appear if the top button is still displayed, and the word world will appear if the bottom button is still displayed.