I have a package for making interactive plots using htmlwidgets
and I would like to expose some of the client-side state so that e.g. the user can highlight some data points and then call a function in R to get the corresponding row indices.
I found a way to do it using a chromote
headless browser:
library(chromote)
session <- ChromoteSession$new()
session$navigate(someURL)
session$Runtime$evaluate("some JS code")
This works well if I know the URL, i.e. if I open the htmlwidgets
figure in an external browser. However, the default print method on an htmlwidget
object is to create a temporary directory, place the files there, and then serve them locally using the RStudio viewer: https://rstudio.github.io/rstudio-extensions/rstudio_viewer.html.
I’ve spent quite a bit of time on it and I still can’t figure out how to get the URL of the temporary directory htmlwidgets
creates so I could point the headless browser there. Anyone got any ideas?
Edit:
As per @thothal’s suggestions, I’ve opted to saving the widget and then serving it from a custom path. I would like to implement this as a custom S3 method for my package:
print.my_package <- function(x, ..., view = interactive()) {
if (view) {
directory <- tempdir()
path <- paste0(directory, "/index.html")
x$path <<- path
saveWidget(x, path)
rstudioapi::viewer(path)
} else {
...
}
}
However, the trouble is that x$path <<- path
doesn’t seem to work and I can’t export the path for later use. Not sure what the problem is, I’ve tested the scoping assignment with custom S3 classes & it seems to work fine.
Instead of relying that the print
method stores the widget, you can do that explicitly yourself with the nice side benefit that you know exactly where it is stored.
library(leaflet)
library(htmlwidgets)
## an example htmlwidget
x <- leaflet() %>%
addTiles()
## save it youself
td <- tempdir()
if (!dir.exists(td)) {
dir.create(td)
}
fp <- file.path(td, "index.html")
saveWidget(x, fp)
## if you want you can view the file as usual
## get default viewer
viewer <- getOption("viewer")
if (!is.null(viewer)) {
viewerFunc <- function(url) {
paneHeight <- x$sizingPolicy$viewer$paneHeight
if (identical(paneHeight, "maximize"))
paneHeight <- -1
viewer(url, height = paneHeight)
}
} else {
viewerFunc <- utils::browseURL
}
viewer(fp)
fp ## now you know where your file sits
1