Skip to content

Commit

Permalink
Add nullOnKeyRelease option
Browse files Browse the repository at this point in the history
  • Loading branch information
DavidBarke committed May 23, 2024
1 parent e1f77a0 commit 8d25cb1
Show file tree
Hide file tree
Showing 7 changed files with 68 additions and 21 deletions.
5 changes: 3 additions & 2 deletions DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,12 @@ License: Apache License (>= 2)
Encoding: UTF-8
LazyData: true
Roxygen: list(markdown = TRUE)
RoxygenNote: 7.1.1
RoxygenNote: 7.2.3
Imports:
htmltools,
shiny,
jsonlite
jsonlite,
glue
URL: https://github.com/r4fun/keys
BugReports: https://github.com/r4fun/keys/issues
Suggests:
Expand Down
4 changes: 3 additions & 1 deletion R/add_key.R
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
addKeys <- function(
inputId,
keys,
nullOnKeyRelease = FALSE,
session = shiny::getDefaultReactiveDomain()
){
if (is.null(session)) alert_null_session()
Expand All @@ -17,7 +18,8 @@ addKeys <- function(
"add_mousetrap_binding",
list(
id = inputId,
keys = x
keys = x,
nullOnKeyRelease = nullOnKeyRelease
)
)
}
Expand Down
8 changes: 5 additions & 3 deletions R/keys.R
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@
#' @param inputId The input slot that will be used to access the value.
#' @param keys A character vector of keys to bind. Examples include, `command`,
#' `command+shift+a`, `up down left right`, and more.
#' @param global Should keys work anywhere? If TRUE, keys are triggered when
#' @param global Should keys work anywhere? If [TRUE], keys are triggered when
#' inside a textInput.
#' @param nullOnKeyRelease If [TRUE], input will be set to [NULL] after keys were
#' released.
#'
#' @examples
#' \dontrun{
Expand All @@ -31,8 +33,8 @@
#' }
#'
#' @export
keysInput <- function(inputId, keys, global = FALSE) {
keysInput <- function(inputId, keys, global = FALSE, nullOnKeyRelease = FALSE) {
htmltools::tagList(
keys_js(inputId, keys, global)
keys_js(inputId, keys, global, nullOnKeyRelease)
)
}
40 changes: 31 additions & 9 deletions R/utils.R
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,37 @@ minify <- function(x) {

#' @importFrom htmltools tags
#' @importFrom jsonlite toJSON
keys_js <- function(id, keys, global = FALSE) {
if (global) global <- "Global"
else global <- ""

x <- sprintf("$(document).on('shiny:sessioninitialized', function() {
Mousetrap.bind%s(%s, function(e, combo) {
Shiny.setInputValue('%s', combo, {priority: 'event'});
});
});", global, toJSON(keys), id)
keys_js <- function(id, keys, global = FALSE, nullOnKeyRelease = FALSE) {
x <- if (!nullOnKeyRelease) {
glue::glue(
"$(document).on('shiny:sessioninitialized', function() {",
" Mousetrap.{{bindFunc}}({{keys}}, function(e, combo) {",
" Shiny.setInputValue('{{id}}', combo, {priority: 'event'});",
" });",
"});",
bindFunc = if (global) "bindGlobal" else "bind",
keys = jsonlite::toJSON(keys),
id = id,
.open = "{{",
.close = "}}"
)
} else {
glue::glue(
"$(document).on('shiny:sessioninitialized', function() {",
" Mousetrap.{{bindFunc}}({{keys}}, function(e, combo) {",
" Shiny.setInputValue('{{id}}', combo, {priority: 'event'});",
" }, 'keydown');",
" Mousetrap.{{bindFunc}}({{keys}}, function(e, combo) {",
" Shiny.setInputValue('{{id}}', null, {priority: 'event'});",
" }, 'keyup');",
"});",
bindFunc = if (global) "bindGlobal" else "bind",
keys = jsonlite::toJSON(keys),
id = id,
.open = "{{",
.close = "}}"
)
}

tags$head(
tags$script(
Expand Down
15 changes: 12 additions & 3 deletions inst/js/handlers.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,17 @@
$( document ).ready(function() {
Shiny.addCustomMessageHandler('add_mousetrap_binding', function(arg) {
Mousetrap.bind(arg.keys, function() {
Shiny.setInputValue(arg.id, arg.keys, {priority: 'event'});
});
if (arg.nullOnKeyRelease) {
Mousetrap.bind(arg.keys, function() {
Shiny.setInputValue(arg.id, arg.keys, {priority: 'event'});
}, 'keydown');
Mousetrap.bind(arg.keys, function() {
Shiny.setInputValue(arg.id, null, {priority: 'event'});
}, 'keyup');
} else {
Mousetrap.bind(arg.keys, function() {
Shiny.setInputValue(arg.id, arg.keys, {priority: 'event'});
});
}
})
Shiny.addCustomMessageHandler('remove_mousetrap_binding', function(arg) {
Mousetrap.unbind(arg.keys);
Expand Down
7 changes: 5 additions & 2 deletions man/keysInput.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 9 additions & 1 deletion man/updateKeys.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 8d25cb1

Please sign in to comment.