Several questions about the TextInput element

PennController for IBEX Forums Support Several questions about the TextInput element

Viewing 9 posts - 1 through 9 (of 9 total)
  • Author
    Posts
  • #6317
    mschrumpf
    Participant

    Hello everyone.
    I want to do a few different things with the TextInput element. I haven’t found solutions for any of these by looking through the documentation and forum.

    1) Is there a way to auto-focus a TextInput (or any element, for that matter) when a trial is loaded? I would like my participants to be able to enter text (or select a button etc.) immediately when the trial is shown on the screen, without them having to press tab or click in it first. (This seems to work sometimes, but not always. For example, I have a trial with a canvas of several input elements for collecting demographic data in my current experiment where the last input is focused by default.)

    2) Is there a way to restrict which inputs can be made in a TextInput element? I want my participants to enter their age in numbers into one of the fields. I am aware that you can test whether a number-only input has been made, but it’s difficult to make that transparent to the participant.

    3) Is there a way to label TextInputs like you would in HTML, so that the browser can tell what kind of input is being asked and offer auto-completion suggestions to the user?

    4) Is there a way to log only certain key presses/entries made in a TextInput when using .log() or .log(“first”) on them? I want to record the timestamp for when the first actual letter has been entered into a TextInput. I would like to avoid logging the time for when, e.g., a participant presses shift for the first time while trying to come up with an answer.

    I hope I was able to get the point across on what I’m trying to do. Thanks in advance for your help.

    Matthias

    #6319
    Jeremy
    Keymaster

    Hello Matthias,

    1) As you noticed, the latest printed TextInput element is the one that gets focused by default. Just print the TextInput that you want to auto-focus last, e.g: getTextInput("inputAlter").print( 400, 0, getCanvas("Canvas") )

    2) There is no straightforward way to do that for TextInput elements in PennController. You’d have to inject some HTML and find a way to save its value, like this for example: newHtml("alter", "<input type='number' id='alter' name='alter' min='1' max='120'>").print( 400, 0, getCanvas("Canvas") ). Then of course you’ll need to adapt any test you had on TextInput so it now checks the value of the HTML input element (e.g. newFunction( ()=>$("#alter").val().match(/^\d+$/) ).testNot.is(null)) and if you need to set a Var element, this is what you’d do: newVar("Alter").global().set( v=>$("#alter").val() )

    3) See point above if you want to use native-HTML features

    4) You can use .log("all") but then the format of the lines in the results file is special. You get four lines for one TextInput element beside the “Final” one, with the relevant information reported in the Comments column for three of them. One line reports how many key presses there were, one line reports the successive Keys that were pressed, one line reports the timecodes of each of those key presses, and one line reports the content of the input box after each of those key presses. The values are separated by commas, coded as %2C to prevent artificially adding extra columns to the results file.

    Example:

    1604596974,MD5,PennController,0,0,Angaben,NULL,TextInput,inputGeboren,NTypingEvents,8,1604596936977,33,weiblich,rechtshändig,Travail,sadfsad,nein,saddsf,asdfdsa,All saved%2C see documentation
    1604596974,MD5,PennController,0,0,Angaben,NULL,TextInput,inputGeboren,TypingEvent,Keys,NULL,33,weiblich,rechtshändig,Travail,sadfsad,nein,saddsf,asdfdsa,Shift%2CT%2Cr%2Ca%2Cv%2Ca%2Ci%2Cl
    1604596974,MD5,PennController,0,0,Angaben,NULL,TextInput,inputGeboren,TypingEvent,Texts,NULL,33,weiblich,rechtshändig,Travail,sadfsad,nein,saddsf,asdfdsa,%2C%2CT%2CTr%2CTra%2CTrav%2CTrava%2CTravai
    1604596974,MD5,PennController,0,0,Angaben,NULL,TextInput,inputGeboren,TypingEvent,Times,NULL,33,weiblich,rechtshändig,Travail,sadfsad,nein,saddsf,asdfdsa,1604596929424%2C1604596930876%2C1604596931456%2C1604596931566%2C1604596931782%2C1604596931866%2C1604596932002%2C1604596932132

    It’s ugly, but it’s easy to parse in R, for example, by splitting the Comments column using %2C. In this example, you can see from the second line that my first key press was the Shift key, and my second key press was the key T. The last line tells me that I pressed T 1604596930876-1604596929424=1452ms after I pressed Shift

    Let me know if you have questions

    Jeremy

    #6330
    mschrumpf
    Participant

    Hello Jeremy,
    thank you very much for your answer.
    Regarding the first three questions: As you correctly guessed, this is about the demographic data trial which we already discussed in another thread. I also have an HTML version of that trial, but I chose to re-make it in pcIBEX so that I could log the data that is entered here to each line of the results file.
    Is it possible to achieve the same thing with inputs made to an HTML element? I imagine one would have to get those inputs, split them up and save them as global variables. If that can be accomplished, points one, two and three would already be solved in my HTML file.

    Regarding question 4, that’s pretty much what I expected and I’ll talk this one through with my team. I am now wondering if I could simply create a new key press element for all letters on the keyboard and log the time for the first time one of them is pressed.

    Thank you very much for your help.
    Matthias

    #6331
    Jeremy
    Keymaster

    Hello Matthias,

    As I mentioned in point 2, you can retrieve the value of an HTML field and store it in a Var element, which means you can use log to append the value at the end of the results lines. Here’s a full example:

    newTrial(
        newVar("Alter").global()
        ,
        newHtml("alter", "<input type='number' id='alter' name='alter' min='1' max='120'>").print()
        ,
        newButton("Next").print().wait( 
            getVar("Alter").set( v=>$("#alter").val() ).testNot.is('')
        )
    )
    .log("alter", getVar("Alter"))

    Re. point 4, what you describe seems similar to using .log('all') except that it would be less reliable (eg. the first printable keypress could correspond to an uncaptured diacritic character, or the participant could press a key outside the input field that would then be wrongly detected). Is there something that dissuades you from using the .log('all') solution?

    Jeremy

    #7499
    nasimbhmn
    Participant

    Hello Jeremy,

    I have a question related to this topic.
    In your example above (point number 2) it is not clear if “alter” refers to the input field name or its id, or the html file. I do not understand how you retrieve the value from html input field.

    Here is what I need to do:
    I have an html file with multiple text input fields and I want to allow participants to move on to the next page if (1) they have completed all fields and (2) if one of these fields equals exactly 100 (it’s an input field whose value is automatically computed according to the value of two other fields). Can you help me with adding condition (2) to the code below?

    This is the input field in my html document “demographics”:

    
    <input name="useTotal" type="text" id="sum" class="obligatory" readonly="TRUE">
    

    And here is the script on PCIbex with condition (1) implemented:

    
    newTrial("consent_demog",
    newHtml("demographics", "demographic.html")
            .checkboxWarning("Required") 
            .radioWarning("Required")
            .inputWarning("Required")
            .print()
            .log()
    
    newButton("Continue")
            .print()
            .wait(
                getHtml("demographics").test.complete()
                .failure(getHtml("consent").warn())
                )
    )
    
    #7501
    Jeremy
    Keymaster

    Hello,

    The expression $("#alter") is a jQuery expression, where you can select an element by targeting its id attribute in the string simply by prefixing a # character. Your input element’s id being “sum”, you can get a jQuery object pointing to it using $("#sum")

    You can use a Function element to dynamically test the value of that input element in the Button’s wait command:

    newButton("Continue")
        .print()
        .wait(
            getHtml("demographics").test.complete()
              .failure( getHtml("demographics").warn() )
              .and(
                newFunction(()=>$("#sum").val())
                    .test.is(100)
                    .failure( newText("must be 100").print() )
              )
        )

    (Note that your original code has getHtml("consent") where it should have getHtml("demographics"))

    Jeremy

    #7503
    nasimbhmn
    Participant

    Thanks for your answer, Jeremy. You’re right about the last note. I just changed names/labels after I pasted the copied chunk, but apparently, I forgot to change the last part.

    I tried your solution, and here are the two errors I got:
    1- A pop-up error: “There must be some items in the running order!”
    2- PennController Debug error: “Command ‘and’ unknown on Button element”

    As for the first error, there is nothing wrong with other parts of my script. When I comment the .add() part, it works fine.

    Thank you very much for your help.
    Best, Nasim

    #7504
    Jeremy
    Keymaster

    Check your parentheses: and should attach to the Html element’s test command (as it does in the bit of code that I gave) not to the Button element

    Jeremy

    #7506
    nasimbhmn
    Participant

    Great! It worked.
    Thanks a lot!

    Best, Nasim

Viewing 9 posts - 1 through 9 (of 9 total)
  • You must be logged in to reply to this topic.