Search code examples
rshinyslick.jsslickr

Get the current image name of a slickR slideshow in shiny


Below is a shiny app which displays a slideshow of images with the slickR package. How to get the name of the current image?

library(shiny)
library(slickR)

ui <- fluidPage(
  tags$div(
      slickROutput("slickr", width="500px"),
      style = "margin-left:100px;"
  )
)

server <- function(input, output) {

  imgs <- list.files("~/", pattern=".png", full.names = TRUE)

  output[["slickr"]] <- renderSlickR({
    slickR(imgs)
  })

}

# Run the application 
shinyApp(ui = ui, server = server)

Solution

  • Here is a solution with a MutationObserver:

    library(shiny)
    library(slickR)
    
    js <- "
    $(document).ready(function(){
      var ss = document.getElementById('slickr');
      // create an observer instance
      var observer = new MutationObserver(function(mutations) {
        var index = $(ss).find('.slick-current').data('slick-index');
        Shiny.setInputValue('imageIndex', parseInt(index)+1);
      });
      // configuration of the observer
      var config = {subtree: true, attributes: true};
      // observe 
      observer.observe(ss, config);
    })
    "
    
    ui <- fluidPage(
      tags$head(
        tags$script(HTML(js))
      ),
      textOutput("imgName"),
      tags$hr(),
      tags$div(
          slickROutput("slickr", width="500px"),
          style = "margin-left:100px;"
      )
    )
    
    server <- function(input, output) {
    
      imgs <- list.files("~/", pattern=".png", full.names = TRUE)
    
      output[["slickr"]] <- renderSlickR({
        slickR(imgs)
      })
    
      output[["imgName"]] <- renderText({
        paste0("CURRENT IMAGE: ", basename(imgs[input[["imageIndex"]]]))
      })
    
    }
    
    # Run the application 
    shinyApp(ui = ui, server = server)
    

    enter image description here

    Another solution, simpler: replace js with

    js <- "
    $(document).ready(function(){
      $('#slickr').on('setPosition', function(event, slick) {
        var index = slick.currentSlide + 1;
        Shiny.setInputValue('imageIndex', index);
      });
    })"