I am ultimately trying to capture the time it takes a user to click on a series of histograms after they are displayed. However, in the example app below, a javascript error appears at the loading of the app:
Uncaught TypeError: Cannot set properties of null (setting 'onclick') at HTMLDocument. ((index):31:30) at e (jquery.min.js:2:30038) at t (jquery.min.js:2:30340)
Presumably this is because document.getElementById("img") doesn't find img at the loading of the app, but I don't know how to resolve that.
I can get this to work when the histogram is displayed outside of the renderUI, but I need to change the histogram dynamically from the server, so I need this to work with a rendered UI.
shinyApp(
ui = fluidPage(
tags$script('
// ------ javascript code ------
$(document).ready(function(){
// function to set Shiny input value to current time:
const clockEvent = function(inputName){Shiny.setInputValue(inputName, new Date().getTime())}
// trigger when the value of output id "img" changes:
$(document).on("shiny:value",
function(event){
if (event.target.id === "img") {clockEvent("displayed_at")}
}
)
// trigger when the image, after being sent or refreshed, is clicked:
document.getElementById("img")
.onclick = function(){clockEvent("reacted_at")}
})
// ------------------------------
'),
sidebarLayout(
sidebarPanel(
actionButton(inputId="render_dynamic", label= "Create Dynamic UI")
),
mainPanel(
uiOutput("dynamic")
)
)
),
server = function(input, output) {
output$img <- renderImage({
outfile <- tempfile(fileext='.png')
png(outfile, width=400, height=400)
hist(rnorm(100))
dev.off()
list(src = outfile,
contentType = "image/jpeg")
},
deleteFile = FALSE)
output$reaction_time <- renderPrint(paste('reaction time (ms)', input$reacted_at - input$displayed_at))
output$dynamic <- renderUI({
req(input$render_dynamic > 0)
div(id = 'image_container',
imageOutput("img", click = "photo_click"),
textOutput("reaction_time"))
})
}
)
renderUI.renderImageis also reactive, so you can change the histogram from the server withoutrenderUI. Is there any reason why you don't userenderPlot?