oTree Forum >

Key press task assitance

#1 by Vincent (edited )

Hello all,

I am currently coding an experiment where I intend on using a task in which subjects are meant to alternately press the 'a' and 'k' keys on their keyboard with a timer that counts down from 3 seconds, refreshing upon the next key press.
I have been trying to find some reference for a task like this, but have had no luck, the best I have found is a code for recording any key or button press. I am using PyCharm to code the experiment.
If anyone has any advice or knows where I can find some reference for this it would be much appreciated.
Thank you.

Kind regards,


#2 by gr0ssmann

This is pretty simple to do using live pages.

Just code up a function and event listener that waits for keypresses, then invoke liveSend(). Handle the keypress within the live_method and give subject feedback using liveRecv().

#3 by Vincent

I will try this, thank you very much!

#4 by Paul1 (edited )

Hi Vincent,

Did you have any chance finding a solution? I am trying to implement the same function. In the first step I am simply trying to record when a participant press the button "a" or "b" on keyboard, and I am unable to do this. Here "a_press" and "b_press" is just the variable defined on Player level. Here's what I did.


    document.addEventListener("keypress", function onPress(event) {
    if (event.keyCode === 65 || event.key == 'a') {
        document.getElementById("a_press").setAttribute("value", "1");
    if (event.keyCode === 66 || event.key == 'b') {
        document.getElementById("b_press").setAttribute("value", "1");

    document.addEventListener("DOMContentLoaded", function (event) {

#5 by ccrabbe

Hi Paul1 -

Specifically what problem or error are you encountering?

I would suggest using console.log statements in your javascript code, and checking the values they print out in your browser's javascript console.  If you put one inside each of those 'if' blocks you will get a printout if either of them are actually getting executed.  You could also put one as the first line inside your onPress function to print out a line when it's called (to make sure it's being called), and have it print out event.keyCode (or just the whole event object) to help you debug what's happening when an A or a B are pressed.

More information about *how* it's not working will help us be able to help you with your specific problems.


#6 by Vincent

Hi Paul,

I am still working through the code, but once I've got it working I'll get back to you with how I did it!

- Vincent

#7 by gr0ssmann

I have repeatedly used code that looked like this:

    window.onkeypress = function (e) {
        console.log("charCode = " + e.charCode);
        if (e.charCode == 99) {
            // do something

Note how console.log will show you the charCode to be used in the if statement.

#8 by Paul1 (edited )

Thanks to all of you for your help! I am fairly new to all this and appreciate learning best practices of using console.log. If this can help someone, I was able to work out something like:

In the html
        <input type="hidden" value="0" name="a_press" id="a_press" onchange="liveSend('pressed-a')">
        <input type="hidden" value="0" name="b_press" id="b_press" onchange="liveSend('pressed-b')">
In the script

    var keys=''
    document.addEventListener("keypress", function onPress(e) {
        get = window.event?event:e
        key = get.keyCode?get.keyCode:get.charCode;
        letter = String.fromCharCode(key);

        console.log("charCode = " + e.charCode);
        console.log("get = " + get);
        console.log("key = " + key);
        console.log("letter = " + letter);
        console.log("keys = " + keys);

        if (e.charCode == 65 || e.charCode == 97) {
        document.getElementById("a_press").setAttribute("value", "1"); console.log(a_press);
        if (e.charCode == 66 || e.charCode == 98) {
        document.getElementById("b_press").setAttribute("value", "1"); console.log(b_press);
    I am left with sending the live changes to 'a_press' and 'b_press' to be able to increment my player.a_press and player.b_press variables, but hopefully I should be able to figure it out.

#9 by Vincent

Hello, thank you for all of the advice and help, I have been able to get the task working.
I am trying to add a countdown timer to the task now, which resets upon each key-press when the alternate key is pressed.
The issue I'm running into is that the timer resets on top of the existing timer, with both timers existing until the previous timer reaches 0, this occurring with as many timers running on top of each other as the number of key-presses before each timer reaches 0.
Any advice for having the timer reset without a previous timer still running would be appreciated.
This is my current code:

in html:
<div id="timeElm" style=" font-size: 500%; color: red; font-weight: 500" align="middle"></div>
<div id="timeElm2" align="middle" style="display: none; font-size: 500%; color: red; font-weight: 500"></div>

in script:

    var current_key;

       var keys=''
    document.addEventListener("keypress", function onPress(e) {

        if (e.charCode == 97) {
        document.getElementById("Key_a").style.display = "block";
        document.getElementById("Key_k").style.display = "none";
        document.getElementById("Press_key").style.display = "none";
        document.getElementById("timeElm").style.display = "none";
        document.getElementById("timeElm2").style.display = "block";


        if (e.charCode == 107) {
        document.getElementById("Press_key").style.display = "none";
        document.getElementById("Key_a").style.display = "none";
        document.getElementById("Key_k").style.display = "block";
        document.getElementById("timeElm").style.display = "block";
        document.getElementById("timeElm2").style.display = "none";


let timeElm = document.getElementById('timeElm');
let timeElm2 = document.getElementById('timeElm2');

let timer = function(x) {
 if(x === -1) {

 timeElm.innerHTML = x;

 return setTimeout(() => {timer(--x)}, 1000)

let timer2 = function(x2) {
 if(x2 === -1) {

 timeElm2.innerHTML = x2;

 return setTimeout(() => {timer2(--x2)}, 1000)


Write a reply

Set forum username