Hi all,
I have been trying (and failing) to get end-on-key-release functionality to work on Pavlovia. I have searched the forum but have not been able to find or adapt any past question to my specific use-case.
This is the functionality I am trying to achieve online.
I am able to get this to work perfectly in builder, but I am unable to replicate the effect on Pavlovia.
I am using the following Auto>JS code in the Each Frame
tab:
var continuing, kb, remainingKeys;
kb = new core.Keyboard({psychoJS: psychoJS, clock: new util.Clock(), waitForStart: true})
continuing = true;
while (continuing) {
remainingKeys = kb.getKeys({"waitRelease": true});
if (remainingKeys) {
for (var key, _pj_c = 0, _pj_a = remainingKeys, _pj_b = _pj_a.length; (_pj_c < _pj_b); _pj_c += 1) {
key = _pj_a[_pj_c];
if ((key.name === "space")) {
continuing = false;
}
}
}
}
This is a link to the gitlab, the experiment is currently piloting and I am not sure if there is a way to make it public without using credits.
Currently, the experiment shows the first frame âBefore Textâ and allows for no keypresses or really any interaction without force quitting.
Again, the functionality I am looking for is as follows:
Show Square > Wait for keypress and release > Show Square > repeat
Thank you for your time!
Hi David,
I managed to build an experiment that does what youâre after. Itâs bit hacky though, but it works. Here is the link: https://gitlab.pavlovia.org/tpronk/demo_keyup
Below some notes on how I got here:
- Looking a the source code of
getKeys()
, I noticed that waitRelease == true
didnât actually do anything. https://psychopy.github.io/psychojs/core_Keyboard.js.html#line158
- I did notice there were some other functions that could be useful, namely
getEvents()
, which returns all keyboard events since the start of the routine and clearEvents()
, which empties it again.
- I built an algorithm that loops through the events returned by
getEvents()
, looks for keydown event, followed by a keyup event. If both are present, it calculates how much time passed between them and ends the routine
- To get this to work I needed to configure the Keyboard component in a particular way: Force end of Routine disabled, and the key youâre looking for (âspaceâ) should not be in the list of allowedKeys.
Hope this helps!
Best, Thomas
2 Likes
Hi Thomas,
First, thank you so much for taking the time to look into this and create a solution! I had seen that there were issues using the keyboard
library and I didnât really know where to go from there.
Trying out the experiment that youâve linked ends only when I press escape
is that correct? You will see several (sorry!) new data files from me. If I was looking to adapt this into a:
show square>press and release space > repeat
Would I just add a square routine before hand?
I donât know what the etiquette is on forking code so I wanted to make sure I touched base with you!
Again, thank you very much for the assistance!
EDIT I just made some changes to an existing template using your code and it seems to be working perfectly!
This is a link to the template. The only thing I changed was adding the duration as output to the .csv.
I plan on adding this into one of the experiments I am working on, and I will make sure to leave your name in the code! Thank you!!!
Happy to hear this helped you out. I work as a software developer with the PsychoJS team, so feel free to do whatever youâd like with it :). We should also implement the waitRelease in a future version, so I made an issue for that on our GitHub. https://github.com/psychopy/psychojs/issues/198
Good luck with the rest of your study!
1 Like
Hi David,
Iâve been struggling with the same issue for a while. Unfortunately, it seems that the template you provided in your link isnât available anymore. Could you please offer some more details of your solution, or maybe share your script again?
Iâm trying to design a task as follows: The participant has to keep pressed the spacebar for a certain duration. Then, I would like to end the routine at the moment the key is released. Iâve come up with a solution that works for builder, but it doesnât work online⌠Could you help me, please?
Thank you for your time!
Hi Nicolas,
Hmm, I will try and make the template active again. In my example I had the following routines:
before > start2 > after
before contains: a text element that lasts for one second and says âbefore textâ
start2 contains: a keyboard component and a code snippet
The keyboard component is:
- set to accept âyâ and ânâ as responses
- NOT force the end of the routine
- Store all keys
The code snippet has the following in each tab:
- begin routine -
window.kb = kb;
- each frame -
let keyEvents = kb.getEvents();
if (keyEvents .length > 0) {
let keydownTimestamp;
let keyupTimestamp;
let i = 0;
for (; i < keyEvents.length; i++) {
if (keyEvents[i].pigletKey === 'space' && keyEvents[i].status === Symbol.for('KEY_DOWN')) {
//console.log('found keydown at event ' + i);
keydownTimestamp = keyEvents[i].timestamp;
break;
}
}
for (; i < keyEvents.length; i++) {
if (keyEvents[i].pigletKey === 'space' && keyEvents[i].status === Symbol.for('KEY_UP')) {
//console.log('found keyup at event ' + i);
keyupTimestamp = keyEvents[i].timestamp;
break;
}
}
if (keydownTimestamp !== undefined && keyupTimestamp !== undefined) {
console.log('duration ' + (keyupTimestamp - keydownTimestamp));
kb.clearEvents();
continueRoutine = false;
}
}
After text contains: a text element that lasts for one second and says âafter textâ
This seems to only work once deployed in Pavlovia. Please let me know if this helps!
2 Likes
Hi David, sorry for the delay, I was struggling a bit to adapt it to my specific case, but it really helped! Completely solved my problem, thank you so much!
1 Like
Iâm happy to type it out, but it is all @thomas_pronk!
2 Likes