From b3fc4db07069043d0642bd5f824316f6773290d3 Mon Sep 17 00:00:00 2001 From: Dean Attali Date: Mon, 16 Jan 2023 04:45:58 -0500 Subject: [PATCH] support htmlDependency in extendShinyjs; related to #254 --- DESCRIPTION | 2 +- NEWS.md | 1 + R/extendShinyjs.R | 40 ++++++++++++++++++++++++++++++++-------- R/useShinyjs.R | 22 +++++++++++++--------- R/utils.R | 6 +++++- man/extendShinyjs.Rd | 8 ++++---- 6 files changed, 56 insertions(+), 23 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 95c7294..29343f4 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: shinyjs Title: Easily Improve the User Experience of Your Shiny Apps in Seconds -Version: 2.1.0.9001 +Version: 2.1.0.9002 Authors@R: person("Dean", "Attali", email = "daattali@gmail.com", role = c("aut", "cre"), diff --git a/NEWS.md b/NEWS.md index 2b0d1ec..1e846fa 100644 --- a/NEWS.md +++ b/NEWS.md @@ -11,6 +11,7 @@ - Added tests using {shinytest2} - Officially removed all `colourInput()` related functions, after 5 years of being defunct (they exist in the {colourpicker} package) - Replaced `addResourcePath()` with `htmlDependency()` which is more robust and useful for package developers (#260) +- New feature: When using `extendShinyjs()`, the `path` can now be a `htmltools::htmlDependency()` (#254) # shinyjs 2.1.0 (2021-12-20) diff --git a/R/extendShinyjs.R b/R/extendShinyjs.R index 756c100..0c597de 100644 --- a/R/extendShinyjs.R +++ b/R/extendShinyjs.R @@ -6,10 +6,10 @@ #' or \href{https://deanattali.com/shinyjs/}{view the shinyjs webpage} #' to learn more. #' -#' @param script Path to a JavaScript file that contains all the functions. -#' Each function name must begin with "`shinyjs.`", for example -#' "`shinyjs.myfunc`". Note that the path to the file must be discoverable by the browser -#' (meaning that it needs to be in a "www/" directory or available via `addResourcePath()`). +#' @param script Either a path or an [`htmltools::htmlDependency()`] to a JavaScript file +#' that contains all the functions. Each function name must begin with "`shinyjs.`", for example +#' "`shinyjs.myfunc`". Note that if a path is provided, it must be discoverable by the browser +#' (ie. it needs to be in a "www/" directory or available via `addResourcePath()`). #' See 'Basic Usage' below for more details. #' @param text Inline JavaScript code to use instead of providing a file. #' See 'Basic Usage' below. @@ -242,9 +242,11 @@ extendShinyjs <- function(script, text, functions) { if (missing(script) && missing(text)) { errMsg("extendShinyjs: Either `script` or `text` need to be provided.") } - + if (!missing(script) && !missing(text)) { + errMsg("extendShinyjs: Either `script` or `text` need to be provided, but not both.") + } if (missing(functions)) { - errMsg("extendShinyjs: `functions` argument must be provided. See the documentation for `?extendShinyjs` for more details.") + errMsg("extendShinyjs: `functions` argument must be provided.") } isShinyjsFunction <- functions %in% shinyjsFunctionNames("all") @@ -264,8 +266,30 @@ extendShinyjs <- function(script, text, functions) { assign(x, jsFunc, js) }) - # set up the message handlers for all functions - setupJS(jsFuncs, script, text) + jsCodeFuncs <- jsFuncTemplate(jsFuncs) + + if (!missing(text)) { + shinyjsContent <- insertHead( + shiny::tags$script(shiny::HTML(text)), + shiny::tags$script(shiny::HTML(jsCodeFuncs)) + ) + } else if (!missing(script)) { + if (is.character(script)) { + shinyjsContent <- insertHead( + shiny::tags$script(src = script), + shiny::tags$script(shiny::HTML(jsCodeFuncs)) + ) + } else if (inherits(script, "html_dependency")) { + shinyjsContent <- insertHead( + script, + shiny::tags$script(shiny::HTML(jsCodeFuncs)) + ) + } + } + + shiny::tagList( + shinyjsContent + ) } diff --git a/R/useShinyjs.R b/R/useShinyjs.R index 41c4ab8..8891c40 100644 --- a/R/useShinyjs.R +++ b/R/useShinyjs.R @@ -65,18 +65,22 @@ useShinyjs <- function(rmd = FALSE, debug = FALSE, html = FALSE) { jsFuncs <- shinyjsFunctionNames("core") jsCodeFuncs <- jsFuncTemplate(jsFuncs) - # JavaScript to include to turn debug mode on/off (used for seeing more messages) - if (debug) { - initJS <- "shinyjs.debug = true;" + jsCodeVersion <- paste0("shinyjs.version = '", as.character(utils::packageVersion("shinyjs")), "';") + if (identical(getOption("shinyjs.debug", FALSE), TRUE)) { + jsCodeDebug <- "shinyjs.debug = true;" } else { - initJS <- "shinyjs.debug = false;" + jsCodeDebug <- "shinyjs.debug = false;" } - # Add the shinyjs package version as a debugging tool - initJS <- paste0(initJS, "shinyjs.version = '", as.character(utils::packageVersion("shinyjs")), "';") + jsCode <- paste( + jsCodeVersion, + jsCodeDebug, + jsCodeFuncs, + sep = "\n" + ) # include CSS for hiding elements - initCSS <- ".shinyjs-hide { display: none !important; }" + cssCode <- ".shinyjs-hide { display: none !important; }" shinyjsContent <- htmltools::htmlDependency( name = "shinyjs-binding", @@ -85,8 +89,8 @@ useShinyjs <- function(rmd = FALSE, debug = FALSE, html = FALSE) { src = "srcjs", script = "shinyjs-default-funcs.js", head = paste0( - "", - "" + "", + "" ) ) diff --git a/R/utils.R b/R/utils.R index 2a96636..4adad45 100644 --- a/R/utils.R +++ b/R/utils.R @@ -82,8 +82,12 @@ insertHead <- function(...) { shinyjsInlcudeScript <- function(script) { if (missing(script) || is.null(script)) { return(NULL) - } else { + } else if (is.character(script)) { shiny::tags$script(src = script) + } else if (inherits(script, "html_dependency")) { + script + } else { + stop("`script` must be either a URL or an `htmltools::htmlDependency()`", call. = FALSE) } } diff --git a/man/extendShinyjs.Rd b/man/extendShinyjs.Rd index 3242bcd..b6bbcbc 100644 --- a/man/extendShinyjs.Rd +++ b/man/extendShinyjs.Rd @@ -7,10 +7,10 @@ extendShinyjs(script, text, functions) } \arguments{ -\item{script}{Path to a JavaScript file that contains all the functions. -Each function name must begin with "\code{shinyjs.}", for example -"\code{shinyjs.myfunc}". Note that the path to the file must be discoverable by the browser -(meaning that it needs to be in a "www/" directory or available via \code{addResourcePath()}). +\item{script}{Either a path or an \code{\link[htmltools:htmlDependency]{htmltools::htmlDependency()}} to a JavaScript file +that contains all the functions. Each function name must begin with "\code{shinyjs.}", for example +"\code{shinyjs.myfunc}". Note that if a path is provided, it must be discoverable by the browser +(ie. it needs to be in a "www/" directory or available via \code{addResourcePath()}). See 'Basic Usage' below for more details.} \item{text}{Inline JavaScript code to use instead of providing a file.