Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Register repeated keyboard presses in shiny

Tags:

r

shiny

I'm trying to build an application where keyboard presses are captured, however I've run into the issue that if the same keyboard presses are used successively then shiny doesn't seem to register the input. Wondering if there is a way around this.

E.g., here's what I mean.

library(shiny)
runApp( list(ui = bootstrapPage(
    verbatimTextOutput("results"),
    tags$script('
    $(document).on("keydown", function (e) {
       Shiny.onInputChange("down", e.which);
    });'),
    tags$script('
    $(document).on("keyup", function (e) {
                Shiny.onInputChange("up", e.which);
                });')
)
, server = function(input, output, session) {

    output$results = renderPrint({
        print(rnorm(1))
        c(input$down, input$up)
    })
}
))

Typing/releasing different characters on the keyboard generates new input, hence the random number generator is called when these events occur. But typing, say, 'g' 'g' 'g' only registers the first up-down keystrokes and ignores the rest.

like image 756
philchalmers Avatar asked Mar 13 '23 00:03

philchalmers


1 Answers

Shiny.onInputChange only reacts when the js object it references changes, but the way you've written your js the value is being reassigned to the same thing with multiple presses of the same key. An ugly workaround might be something like making the variable be the key presses and a random float in an array.

library(shiny)
runApp( list(ui = bootstrapPage(
  verbatimTextOutput("results"),
  tags$script('
              $(document).on("keydown", function (e) {

              Shiny.onInputChange("down", [e.which,Math.random()]);
              });'),
    tags$script('
                $(document).on("keyup", function (e) {

                Shiny.onInputChange("up",  [e.which,Math.random()]);
                });')
)
, server = function(input, output, session) {

  output$results = renderPrint({
    print(rnorm(1))
    c(input$down[1], input$up[1])
  })
}
  ))

It might be more efficient to eliminate the need to generate random numbers, and pass some potentially useful information back. For example using the timestamp property you could implement some filtering on the key presses.

library(shiny)
runApp( list(ui = bootstrapPage(
  verbatimTextOutput("results"),
  tags$script('
          $(document).on("keydown", function (e) {

          Shiny.onInputChange("down", [e.which,e.timeStamp]);
          });'),
tags$script('
            $(document).on("keyup", function (e) {

            Shiny.onInputChange("up",  [e.which,e.timeStamp]);
            });')
)
, server = function(input, output, session) {

  output$results = renderPrint({
    print(rnorm(1))
    c(input$down[1], input$up[1])
  })
}
  ))
like image 98
user5219763 Avatar answered Mar 28 '23 07:03

user5219763