PennController for IBEX › Forums › Support › Enabling a button after text is entered without pressing Enter
- This topic has 10 replies, 2 voices, and was last updated 4 years, 4 months ago by
Jeremy.
-
AuthorPosts
-
September 21, 2020 at 1:51 pm #6133
mawilson
ParticipantI’d like to set up a text input that collects info from participants. This input should be mandatory, so I want to disable the “Next” button until participants have entered text in the field. In order to avoid confusion, I’d ideally like to just disable the button entirely (i.e., make it unclickable) until a participant has entered text, and then enable it. Again, in order to avoid confusion, I’d like to not require participants to press Enter after typing to make this work, but I can’t seem to find a way to do that. Here’s a minimal working example illustrating what I have so far (https://expt.pcibex.net/ibexexps/mawilson/test/experiment.html):
PennController.ResetPrefix(NULL) Sequence('test') newTrial('test', newTextInput('test_input') .print() , newButton('Next', 'Next') .print() .disable() , getTextInput('test_input') .wait() , getButton('Next') .enable() .wait() )
But this still requires participants to press Enter after typing in the text box. Is there a way to allow the button to be enabled upon text entry without participants having to press Enter?
Edit: I’ve tried using
wait(getTextInput('test_input').testNot.text('')
beforeenable()
for the button element, but the button never actually gets enabled then.September 21, 2020 at 3:24 pm #6139Jeremy
KeymasterHello,
Since I haven’t implemented a callback command for the TextInput element that would listen to keypresses, the best solution is to use a Key element (for which there is a callback command) to listen to keypresses. Now, it reacts to keypresses so fast that immediately checking the value of the TextInput element in the callback block won’t capture the newly pressed key, so you want to add a slight delay, e.g. 5ms before checking it.
Here’s how to do it based on the example you give:
newTrial('test', newTextInput('test_input') .print() , // empty string means any key newKey('').callback( newTimer(5).start().wait() , getTextInput('test_input').test.text(/\w/) .success( getButton('Next').enable() ) .failure( getButton('Next').disable() ) ) , newButton('Next', 'Next') .print() .disable() .wait() )
Let me know if you have any questions
Jeremy
September 21, 2020 at 3:46 pm #6140mawilson
ParticipantThanks! That worked great! This isn’t crucial, but is there a way to disable the button again if they delete the text? It’s not a huge deal if there isn’t.
September 21, 2020 at 3:52 pm #6141Jeremy
KeymasterIsn’t it already the case?
September 21, 2020 at 3:54 pm #6142mawilson
ParticipantSorry, yeah, I just realized that it does that if you use a separate button press to delete the last character. But if you enter multiple characters and hold down backspace to delete everything, it won’t disable it until you press a key again. If there’s no good way around that edge case it shouldn’t be a problem anyway.
-
This reply was modified 4 years, 4 months ago by
mawilson.
September 21, 2020 at 4:11 pm #6144Jeremy
KeymasterIn that case let’s use a good old javascript function:
newTrial('test', newTextInput('testinput') .print() , newFunction( () => $("textarea.PennController-testinput").bind('keyup', e=> getTextInput('testinput').test.text(/\w/) .success( getButton('Next').enable() ) .failure( getButton('Next').disable() ) ._runPromises() ) ).call() , newButton('Next', 'Next') .print() .disable() .wait() )
Jeremy
-
This reply was modified 4 years, 4 months ago by
Jeremy. Reason: fixed errors in code - see messages below
September 21, 2020 at 4:21 pm #6145mawilson
ParticipantNot sure why, but when I try that I get an error message:
[16:20:14] Uncaught SyntaxError: missing ) after argument list (PennController: 0)
. I’ve been messing around trying to fix it but can’t seem to figure out how.Sorry for all the trouble!
Edit: removing the semicolon after
_runPromises()
lets the script run, but the function doesn’t appear to work.September 21, 2020 at 4:39 pm #6149Jeremy
KeymasterI made a few typos after I copy-pasted my code (eg. I had getTextInput("test_input")—gotten rid of _) —things should work now. Sorry about that
Jeremy
September 21, 2020 at 4:41 pm #6150mawilson
ParticipantNo worries! Thank you for all the help!
September 22, 2020 at 1:48 pm #6155mawilson
ParticipantThis is probably similar enough to fit in this thread, but is there a way to do this for a checkbox (i.e., only enable the button when the checkbox is selected). This one is more crucial since it’s for an HTML consent form, and I want to make absolutely sure people can’t get past the form unless the box saying they consent is checked.
September 22, 2020 at 1:56 pm #6158Jeremy
KeymasterHi,
Since there is no checkbox element natively implemented in PennController yet, you’ll need to code the checkbox element yourself, for example as part of an HTML document. Make sure you give it a unique ID or class, and use the method above. Here’s an example:
newTrial( newHtml("form", `<div> <input name='consent' id='consent' type='checkbox'><label for='consent'>I consent</label> </div>`).print() , newFunction( () => $("#consent").change( e=>{ if (e.target.checked) getButton("Next").enable()._runPromises(); else getButton("Next").disable()._runPromises(); }) ).call() , newButton("Next") .disable() .print() .wait() )
Jeremy
-
This reply was modified 4 years, 4 months ago by
-
AuthorPosts
- You must be logged in to reply to this topic.