I am building a barcode scanner application to verify that a primary barcode label matches all secondary barcode labels generated from the primary. The current iteration uses R, shiny and modal dialogs for scanning of the barcode labels.
I would like the app to autofocus on the text input field(s) after the modal pops up so that the user does not have to click the entry field or tab to it before scanning the label. I have read that the JS focus function may be appropriate but I am not sure where this function needs to be implemented. Your help is appreciated.
.libPaths(c(.libPaths(), temp <- tempdir()))
if(!require(shiny)) {install.packages("shiny", lib=temp, repos='http://cran.us.r-project.org')}
if(!require(shinyWidgets)) {install.packages("shinyWidgets", lib=temp, repos='http://cran.us.r-project.org')}
if(!require(shinyalert)) {install.packages("shinyalert", lib=temp, repos='http://cran.us.r-project.org')}
if(!require(devtools)) {install.packages("devtools", lib=temp, repos='http://cran.us.r-project.org')}
if(!require(shinyBarcode)) {devtools::install_github("CannaData/shinyBarcode")}
if(!require(shinyjs)) {install.packages("shinyjs", lib=temp, repos='http://cran.us.r-project.org')}
if(!require(V8)) {install.packages("V8", lib=temp, repos='http://cran.us.r-project.org')}
library(shiny)
library(shinyWidgets)
library(shinyalert)
library(shinyBarcode)
library(shinyjs)
library(V8)
options(shiny.sanitize.errors = TRUE)
options(rsconnect.max.bundle.size="xxxlarge")
ui <- fluidPage(
# must include javascript dependencies
useShinyalert(), # Set up shinyalert
shinyBarcode::includeJsBarcode(cdn = TRUE),
shinyBarcode::barcodeOutput("barcode"),
useShinyjs(),
extendShinyjs(script = "beep.js"),
extendShinyjs(script = "beep2.js"),
)
server <- function(input, output, session) {
vals <- reactiveValues(txt = NULL)
# Create modals
primary <- function(failed = FALSE) {
modalDialog(
textInput("txt", "Scan primary tube"),
footer = NULL,
actionButton("reset", "Reset")
)
}
secondary <- function(failed = FALSE) {
modalDialog(
textInput("txt2", "Scan secondary tube"),
footer = NULL,
actionButton("reset", "Reset")
)
}
# Show modal on startup
showModal(primary())
observeEvent(input$txt, {
if (!is.null(input$txt) && nzchar(input$txt)) {
vals$txt <- input$txt
removeModal()
showModal(secondary())
} else {
showModal(primary(failed = TRUE))
}
})
observeEvent(input$txt2, {
if (!is.null(input$txt2) & nzchar(input$txt2) & input$txt2!="Reset") {
vals$txt2 <- input$txt2
removeModal()
if (vals$txt2==vals$txt) {
js$beep()
showModal(secondary())
}
else if (vals$txt2!=vals$txt) {
js$beep2()
shinyalert("Error", "Primary and secondary labels do not match", type = "error")
showModal(secondary())
}
} else if (!is.null(input$txt2) & nzchar(input$txt2) & input$txt2=="Reset"){
showModal(primary())
} else {
showModal(secondary(failed = TRUE))
}
})
observeEvent(input$reset, {
showModal(primary())
})
output$barcode <- shinyBarcode::renderBarcode(vals$txt)
}
shinyApp(ui = ui, server = server)